MySQL DELETE FROM avec sous-requête comme condition

J’essaie de faire une requête comme celle-ci:

DELETE FROM term_hierarchy AS th WHERE th.parent = 1015 AND th.tid IN ( SELECT DISTINCT(th1.tid) FROM term_hierarchy AS th1 INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015) WHERE th1.parent = 1015 ); 

Comme vous le savez probablement, je veux supprimer la relation parent à 1015 si le même tid a d’autres parents. Cependant, cela me donne une erreur de syntaxe:

 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS th WHERE th.parent = 1015 AND th.tid IN ( SELECT DISTINCT(th1.tid) FROM ter' at line 1 

J’ai vérifié la documentation et exécuté la sous-requête par elle-même, et tout semble vérifier. Quelqu’un peut-il comprendre ce qui ne va pas ici?

Mise à jour : Comme indiqué ci-dessous, MySQL n’autorise pas l’utilisation de la table que vous supprimez dans une sous-requête pour la condition.

Vous ne pouvez pas spécifier la table cible pour la suppression.

Une solution de contournement

 create table term_hierarchy_backup (tid int(10)); <- check data type insert into term_hierarchy_backup SELECT DISTINCT(th1.tid) FROM term_hierarchy AS th1 INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015) WHERE th1.parent = 1015; DELETE FROM term_hierarchy AS th WHERE th.parent = 1015 AND th.tid IN (select tid from term_hierarchy_backup); 

Pour d’autres qui trouvent que cette question cherche à se supprimer en utilisant une sous-requête, je vous laisse cet exemple pour déjouer MySQL (même si certaines personnes semblent penser que cela est impossible):

 DELETE e.* FROM tableE e WHERE id IN (SELECT id FROM tableE WHERE arg = 1 AND foo = 'bar'); 

vous donnera une erreur:

 ERROR 1093 (HY000): You can't specify target table 'e' for update in FROM clause 

Cependant cette requête:

 DELETE e.* FROM tableE e WHERE id IN (SELECT id FROM (SELECT id FROM tableE WHERE arg = 1 AND foo = 'bar') x); 

va bien fonctionner:

 Query OK, 1 row affected (3.91 sec) 

Enveloppez votre sous-requête dans une sous-requête supplémentaire (ici nommée x) et MySQL se fera un plaisir de faire ce que vous demandez.

L’alias doit être inclus après le mot clé DELETE :

 DELETE th FROM term_hierarchy AS th WHERE th.parent = 1015 AND th.tid IN ( SELECT DISTINCT(th1.tid) FROM term_hierarchy AS th1 INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015) WHERE th1.parent = 1015 ); 

Vous devez vous référer à nouveau à l’alias dans l’instruction delete, par exemple:

 DELETE th FROM term_hierarchy AS th .... 

Comme indiqué ici dans la documentation MySQL.

Je l’ai abordé d’une manière légèrement différente et cela a fonctionné pour moi;

J’avais besoin de supprimer secure_links de ma table qui secure_links référence à la table des conditions où il n’y avait plus de lignes de condition. Un script de ménage essentiellement. Cela m’a donné l’erreur – Vous ne pouvez pas spécifier la table cible pour la suppression.

Donc, en cherchant ici l’inspiration, je suis arrivé avec la requête ci-dessous et cela fonctionne très bien. En effet, il crée une table temporaire sl1 utilisée comme référence pour DELETE.

 DELETE FROM `secure_links` WHERE `secure_links`.`link_id` IN ( SELECT `sl1`.`link_id` FROM ( SELECT `sl2`.`link_id` FROM `secure_links` AS `sl2` LEFT JOIN `conditions` ON `conditions`.`job` = `sl2`.`job` WHERE `sl2`.`action` = 'something' AND `conditions`.`ref` IS NULL ) AS `sl1` ) 

Travaille pour moi.

La clause “in” n’est-elle pas dans la suppression … où, extrêmement inefficace, s’il y a un grand nombre de valeurs renvoyées par la sous-requête? Vous ne savez pas pourquoi vous ne vous contentez pas de vous joindre à la table d’origine à partir de la sous-requête sur l’ID à supprimer, plutôt que de nous placer “in (sous-requête)”.?

 DELETE T FROM Target AS T RIGHT JOIN (full subquery already listed for the in() clause in answers above) ` AS TT ON (TT.ID = T.ID) 

Et peut-être répond-on dans “MySQL ne le permet pas”, cependant, cela fonctionne très bien pour moi. FOURNI Je m’assure de bien clarifier ce qu’il faut supprimer (DELETE T FROM Target AS T). Supprimer avec Join in MySQL clarifie le problème DELETE / JOIN.

Si vous voulez faire cela avec 2 requêtes, vous pouvez toujours faire quelque chose de similaire à ceci:

1) récupérer les identifiants de la table avec:

 SELECT group_concat(id) as csv_result FROM your_table WHERE whatever = 'test' ... 

Ensuite, copiez le résultat avec la souris / le clavier ou le langage de programmation sur XXX ci-dessous:

 2) DELETE FROM your_table WHERE id IN ( XXX ) 

Peut-être que vous pourriez le faire en une seule requête, mais c’est ce que je préfère.