MySQL удалить из с подзапросом как условие

Я пытаюсь сделать такой запрос:

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

Как вы, вероятно, можете сказать, я хочу удалить родительское отношение к 1015, если у того же tid есть другие родители. Однако это дает мне синтаксическую ошибку:

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

Я проверил документацию и запустил подзапрос сам по себе, и все это, кажется, проверяет. Кто-нибудь может понять, что здесь не так?

обновление: как ответили ниже, MySQL не разрешает таблицу, которую вы удаляете from используется в подзапросе для условия.

7 ответов


вы не можете указать целевую таблицу для удалить.

решение

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

для других, которые находят этот вопрос, который нужно удалить при использовании подзапроса, я оставляю вам этот пример для перехитрения MySQL (даже если некоторые люди, похоже, думают, что это невозможно сделать):

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

даст вам ошибку:

ERROR 1093 (HY000): You can't specify target table 'e' for update in FROM clause
запрос:
DELETE e.*
FROM tableE e
WHERE id IN (SELECT id
             FROM (SELECT id
                   FROM tableE
                   WHERE arg = 1 AND foo = 'bar') x);

будет работать нормально:

Query OK, 1 row affected (3.91 sec)

оберните свой подзапрос в дополнительный подзапрос (здесь называется x), и MySQL с радостью сделает то, что вы просите.


псевдоним должен быть включен после 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
);

вам нужно снова обратиться к псевдониму в инструкции delete, например:

DELETE th FROM term_hierarchy AS th
....

как описано здесь в документах MySQL.


Я подошел к этому немного по-другому, и он работал для меня;

мне нужно удалить secure_links из моей таблицы, которая ссылается на conditions таблица, в которой больше не осталось строк условий. Сценарий домашнего хозяйства в основном. Это дало мне ошибку - вы не можете указать целевую таблицу для удалить.

поэтому, глядя здесь на вдохновение, я придумал следующий запрос, и он работает просто отлично. Это потому, что он создает временную таблицу sl1 что используется в качестве ссылки для удаления.

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

работает для меня.


не "в" пункт в "удалить"... где крайне неэффективно, если там будет большое количество значений, возвращаемых подзапросом? Не уверен, почему вы не просто внутренний (или правый) присоединитесь к исходной таблице из подзапроса на ID для удаления, а не к нам "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)

и, возможно, на него ответили в "MySQL не позволяет", однако он отлично работает для меня при условии, что я полностью уточню, что удалить (Исключить T из цели как T). удалить с помощью Join в MySQL уточняет проблему удаления / присоединения.


Если вы хотите сделать это с 2 запросами, вы всегда можете сделать что-то подобное этому:

1) Возьмите идентификаторы из таблицы с помощью:

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

затем скопируйте результат с помощью мыши / клавиатуры или языка программирования на XXX ниже:

2) DELETE FROM your_table WHERE id IN ( XXX )

может быть, вы могли бы сделать это в одном запросе, но это то, что я предпочитаю.