MySQL DELETE FROM with subquery as condition

Próbuję zrobić takie zapytanie:

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
);

Jak zapewne wiesz, chcę usunąć relację rodzica do 1015, jeśli ten sam tid ma innych rodziców. Jednak to powoduje błąd składni:

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

Sprawdziłam dokumentację i uruchomiłam samo zapytanie podrzędne i wszystko wydaje się sprawdzać. Czy ktoś może dowiedzieć się, co tu jest nie tak?

Update: zgodnie z odpowiedzią poniżej, MySQL nie zezwala na użycie tabeli, którą usuwasz w zapytaniu podrzędnym dla warunek.

Author: Sam, 2010-12-17

7 answers

Nie można określić docelowej tabeli do usunięcia.

Obejście

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);
 31
Author: ajreal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-17 14:23:32

Dla innych, którzy uważają, że to pytanie chce usunąć podczas korzystania z subquery, zostawiam ci ten przykład przechytrzenia MySQL (nawet jeśli niektórzy uważają, że nie można tego zrobić):

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

Da ci błąd:

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

Jednak to zapytanie:

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

Będzie działać dobrze:

Query OK, 1 row affected (3.91 sec)

Zawiń swoje subquery w dodatkowe subquery (tutaj o nazwie x), a MySQL z przyjemnością zrobi to, o co prosisz.

 208
Author: CodeReaper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-22 13:42:40

Alias powinien być dołączony po słowie kluczowym 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
);
 30
Author: James Wiseman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-03 02:04:10

Musisz ponownie odwołać się do aliasu w instrukcji delete, np.:

DELETE th FROM term_hierarchy AS th
....

Jak opisano tutaj w dokumentach MySQL.

 6
Author: JNK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-03 02:03:49

Podszedłem do tego w nieco inny sposób i u mnie zadziałało;

Musiałem usunąć secure_links z mojej tabeli, która odwoływała się do Tabeli conditions, w której nie było już żadnych wierszy warunkowych. Skrypt porządkowy. To dało mi błąd - nie można określić docelowej tabeli do usunięcia.

Więc szukając inspiracji, wpadłem na poniższe zapytanie i działa dobrze. To dlatego, że tworzy tymczasową tabelę sl1, która jest używana jako odniesienie do Usunąć

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`
            )
Mi pasuje.
 5
Author: Darren Edwards,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-01 11:12:45

Nie jest klauzulą " in " w delete ... gdzie, bardzo nieefektywne, jeśli będzie duża liczba wartości zwracanych z zapytania podrzędnego? Nie wiem, dlaczego nie tylko wewnętrzne (lub prawo) dołączyć z powrotem do oryginalnej tabeli z subquery NA ID do usunięcia, a nie nas "in (subquery)".?

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)

I może jest to odpowiedź w "MySQL na to nie pozwala", jednak dla mnie działa dobrze pod warunkiem, że upewnię się w pełni wyjaśnić, co usunąć (DELETE T z Cel jako T). Delete with Join w MySQL wyjaśnia problem DELETE / JOIN.

 3
Author: Jeff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:19

Jeśli chcesz to zrobić z 2 zapytaniami, zawsze możesz zrobić coś podobnego:

1) chwyć identyfikatory z tabeli za pomocą:

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

Następnie skopiuj wynik za pomocą myszy/klawiatury lub języka programowania do XXX poniżej:

2) DELETE FROM your_table WHERE id IN ( XXX )

Może mógłbyś to zrobić jednym zapytaniem, ale to jest to, co wolę.

 0
Author: TomoMiha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-25 16:05:46