2010-07-26 7 views
85

J'essaie de supprimer de quelques tables à la fois. Je l'ai fait un peu de recherche, et est venu avec cetteComment supprimer de plusieurs tables dans MySQL?

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

Cependant, je reçois cette erreur

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

Je ne l'ai jamais fait une table croix supprimer avant, donc je suis inexpérimenté et coincé pour à présent!

Qu'est-ce que je fais mal?

Répondre

153

Utilisez un JOIN dans l'instruction DELETE.

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 

... pour supprimer seulement de pets_activities

Voir http://dev.mysql.com/doc/refman/5.0/en/delete.html

Pour table unique supprime, mais avec l'intégrité référentielle, il y a d'autres façons de faire avec EXISTS, NOT EXISTS, IN, NOT IN, etc. Mais celui ci-dessus où vous spécifiez à partir de quelles tables supprimer avec un alias avant la clause FROM peut vous sortir de quelques endroits plutôt difficiles plus facilement. J'ai tendance à atteindre un EXISTS dans 99% des cas et puis il y a le 1% où cette syntaxe MySQL prend le jour.

+5

J'ai essayé cette "suppression all in 1 requête" avec 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 – techouse

+1

@cadman Ceci est la vraie bonne réponse; il peut y avoir des arguments contre l'utilisation, mais il est très utile à l'occasion –

+1

+1 Je suis d'accord que cela dans la vraie vraie réponse, puisque la question n'était pas "devrait vous" mais "comment". 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. –

17

Comme il semble être un parent simple,/relation enfant entre pets et pets_activities, vous feriez mieux de créer votre contrainte de clé étrangère avec une cascade de suppression. Ainsi, lorsqu'une ligne pets est supprimée, les lignes pets_activities qui lui sont associées sont automatiquement supprimées.

Ensuite, votre requête devient simple:

delete from `pets` 
    where `order` > :order 
     and `pet_id` = :pet_id 
+0

Supprimer les cascades invitent des accidents horribles. –

+0

Merci Paxdiablo, je ne sais pas encore comment le faire en MySQL mais je vais y réfléchir. – alex

+2

@Erick, à condition que vous ayez configuré l'intégrité référentielle, les suppressions en cascade ne peuvent causer plus de problèmes que la suppression seule. Nous savons déjà que 'pa' est un enfant propre de' p' en raison du mappage 'id/pet_id'. – paxdiablo

2

Je n'ai pas une base de données MySQL pour tester sur le moment, mais avez-vous essayé spécifier les éléments à supprimer avant la clause de? 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 utilisée est limitée aux versions les plus récentes de MySQL.

+1

Cette requête a été exécutée avec succès, cependant, elle n'a supprimé aucune ligne (mais je crois qu'elle devrait l'être). – alex

12

Utilisez cette

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 
+0

Nice - semble mieux et plus facile que d'utiliser JOIN. C'est la meilleure solution que je vois ici .. merci! – gnB

+1

Trouvé une bonne référence pour l'utilisation de ceci et quelques autres options à http://www.mysqltutorial.org/mysql-delete-statement.aspx –

0

Pour toute personne lisant ceci en 2017, voici comment je l'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]