Comment supprimer de plusieurs tables dans MySQL?

116

J'essaye de supprimer de quelques tables à la fois. J'ai fait un peu de recherche et j'ai trouvé ceci

DELETE FROM `pets` p,
            `pets_activities` pa
      WHERE p.`order` > :order
        AND p.`pet_id` = :pet_id
        AND pa.`id` = p.`pet_id`

Cependant, j'obtiens cette erreur

Uncaught Database_Exception [1064]: Vous avez une erreur dans votre syntaxe SQL; consultez le manuel qui correspond à la version de votre serveur MySQL pour la bonne syntaxe à utiliser près de 'p, pets_activitiespa ...

Je n'ai jamais fait de suppression de tableaux croisés auparavant, donc je suis inexpérimenté et coincé pour le moment!

Qu'est-ce que je fais mal?

Alex
la source

Réponses:

204

Utilisez un JOINdans l' DELETEinstruction.

DELETE p, pa
      FROM pets p
      JOIN pets_activities pa ON pa.id = p.pet_id
     WHERE p.order > :order
       AND p.pet_id = :pet_id

Vous pouvez également utiliser ...

DELETE pa
      FROM pets_activities pa
      JOIN pets p ON pa.id = p.pet_id
 WHERE p.order > :order
   AND p.pet_id = :pet_id

... à supprimer uniquement de pets_activities

Regarde ça .

Pour les suppressions de table unique, mais avec l' intégrité référentielle, il y a d' autres façons de faire avec EXISTS, NOT EXISTS, IN, NOT INet etc. Mais celui ci - dessus vous permet de spécifier à partir de laquelle des tables à supprimer avec un alias avant la FROMclause peut vous sortir de quelques assez serré taches plus facilement. J'ai tendance à atteindre un EXISTSdans 99% des cas, puis il y a le 1% où cette syntaxe MySQL prend la journée.

cadman
la source
7
J'ai essayé cette requête "supprimer tout en 1" en joignant 6 grandes tables (tout le monde environ ~ 15k lignes) et la requête a pris 155 secondes pour supprimer 63 lignes dans 6 tables: O
Klemen Tušar
1
@cadman C'est la vraie bonne réponse; il peut y avoir des arguments contre son utilisation, mais c'est très utile à l'occasion
Simon Christian
1
+1 Je suis d'accord pour dire que c'est la vraie bonne réponse, puisque la question n'était pas "devriez-vous" mais "comment faire". Cependant, je serais intéressé d'entendre parler du 1% parce que je ne peux pas penser à une seule situation où cela serait préférable.
Erick Robertson
2
@techouse, avez-vous rejoint et filtré sur les indices? 15k x 15k x 15k x 15k 15k x 15k est 11 millions. Cela a-t-il SELECTpris autant de temps?
Paul Draper
6
Vous pouvez également utiliser LEFT JOIN, ce qui est utile si la deuxième table n'a pas d'entrées correspondantes, sinon rien ne sera supprimé.
Lexib0y
20

Comme cela semble être une simple relation parent / enfant entre petset pets_activities, vous feriez mieux de créer votre contrainte de clé étrangère avec une cascade de suppression.

De cette façon, lorsqu'une petsligne est supprimée, les pets_activitieslignes qui lui sont associées sont également supprimées automatiquement.

Ensuite, votre requête devient simple:

delete from `pets`
    where `order` > :order
      and `pet_id` = :pet_id
paxdiablo
la source
3
@Erick, à condition que vous ayez configuré l'intégrité référentielle, les suppressions en cascade ne peuvent pas causer plus de problèmes que la suppression seule. Nous savons déjà que pac'est un bon enfant de en praison de la id/pet_idcartographie.
paxdiablo
14
Eh bien, vous avez vos propres pensées, mais il semble que vous évitez une grande partie de la puissance du SGBD. Les suppressions en cascade font autant partie de la gestion des données que les déclencheurs, les procédures stockées ou les contraintes et elles ne sont dangereuses que si vous ne savez pas ce que vous faites. Pourtant, je ne discuterai pas davantage, nous devrons simplement accepter de ne pas être d'accord.
paxdiablo
8
Erick, maintenant tu as piqué mon intérêt. Comment garantir l'intégrité des données au sein de la base de données sans contraintes?
paxdiablo
4
@Erick a déclaré: "Je n'utilise pas non plus de déclencheurs, de procédures stockées ou de contraintes." Ah, vous utilisez Excel. :-)
james.garriss
4
Je veux juste poursuivre sur ce point. J'ai changé ma position sur la suppression des cascades dans cette situation. J'ai fait partie d'un nouvel environnement SQL qui les utilisait, les utilisait bien et ils étaient très organisés. Dans ce système, il a très bien fonctionné à notre avantage d'avoir ces cascades en place. Cela empêchait certainement les données orphelines et n'était pas dangereux. Le problème est que tous ceux qui travaillent avec la base de données doivent comprendre comment les utiliser en toute sécurité. Mais il y a toujours des risques lorsque les développeurs juniors effectuent des modifications de base de données sans supervision.
Erick Robertson
14

Utilisez ceci

DELETE FROM `articles`, `comments` 
USING `articles`,`comments` 
WHERE `comments`.`article_id` = `articles`.`id` AND `articles`.`id` = 4

ou

DELETE `articles`, `comments` 
FROM `articles`, `comments` 
WHERE `comments`.`article_id` = `articles`.`id` AND `articles`.`id` = 4
RN Kushwaha
la source
1
J'ai
Mavelo
3

Je n'ai pas de base de données mysql à tester pour le moment, mais avez-vous essayé de spécifier ce qu'il faut supprimer avant la clause from? Par exemple:

DELETE p, pa FROM `pets` p,
        `pets_activities` pa
  WHERE p.`order` > :order
    AND p.`pet_id` = :pet_id
    AND pa.`id` = p.`pet_id`

Je pense que la syntaxe que vous avez utilisée est limitée aux nouvelles versions de mysql.

Brandon Horsley
la source
1
Cette requête s'est exécutée avec succès, cependant, elle n'a supprimé aucune ligne (mais je pense qu'elle aurait dû).
alex le
2

La syntaxe me semble correcte ... essayez de la changer pour l'utiliser INNER JOIN...

Jetez un œil à ceci .

André Gallo
la source
7
Dommage que vous n'ayez pas inclus la solution réelle, car le lien est correct!
mycroes
1

Pour tous ceux qui liront ceci en 2017, voici comment j'ai fait quelque chose de similaire.

DELETE pets, pets_activities FROM pets inner join pets_activities
on pets_activities.id = pets.id WHERE pets.`order` > :order AND 
pets.`pet_id` = :pet_id

Généralement, pour supprimer des lignes de plusieurs tables, la syntaxe que je suis est donnée ci-dessous. La solution est basée sur l'hypothèse qu'il existe une relation entre les deux tables.

DELETE table1, table2 FROM table1 inner join table2 on table2.id = table1.id
WHERE [conditions]
Kalesh Kaladharan
la source
1

J'ai trouvé cet article qui vous montre comment supprimer des données de plusieurs tables à l'aide de l' instruction MySQL DELETE JOIN avec une bonne explication.

entrez la description de l'image ici

Ravi Makwana
la source