100

我正在尝试进行这样的查询:

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

您可能会说,如果同一个 tid 有其他父母,我想删除与 1015 的父关系。但是,这会给我一个语法错误:

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 不允许您要从中删除的表在条件的子查询中使用。

4

9 回答 9

316

对于在使用子查询时发现此问题希望删除的其他人,我将这个示例留给您以智取 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 会很高兴地按照您的要求进行操作。

于 2012-10-19T07:42:39.007 回答
48

别名应包含在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
);
于 2010-12-17T14:24:35.767 回答
44

您不能指定要删除的目标表。

一种解决方法

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);
于 2010-12-17T14:23:32.553 回答
13

您需要在 delete 语句中再次引用别名,例如:

DELETE th FROM term_hierarchy AS th
....

如 MySQL 文档中所述。

于 2010-12-17T14:20:13.413 回答
9

我以稍微不同的方式处理这个问题,它对我有用;

我需要secure_links从我的表中删除,该conditions表引用了不再有任何条件行的表。基本上是一个管家脚本。这给了我错误-您不能指定要删除的目标表。

所以在这里寻找灵感,我想出了下面的查询,它工作得很好。这是因为它创建了一个临时表sl1,用作 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`
            )

为我工作。

于 2014-08-01T11:12:45.847 回答
5

删除中的“in”子句不是...哪里效率极低,如果要从子查询返回大量值?不知道为什么你不只是内部(或右)加入从ID上的子查询中删除的原始表,而不是我们的“in(子查询)”。?

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 不允许它”中得到了回答,但是,它对我来说工作正常,前提是我确保完全阐明要删除的内容(从目标 AS T 中删除 T)。 在 MySQL 中使用 Join 删除澄清了 DELETE / JOIN 问题。

于 2015-11-11T19:59:32.670 回答
2

如果你想用 2 个查询来做到这一点,你总是可以做类似的事情:

1)从表中获取ID:

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

然后用鼠标/键盘或编程语言将结果复制到下面的XXX:

2) DELETE FROM your_table WHERE id IN ( XXX )

也许您可以在一个查询中执行此操作,但这是我更喜欢的。

于 2017-12-25T16:05:46.887 回答
0

您可以在删除语句上以这种方式使用别名

DELETE  th.*
FROM term_hierarchy th
INNER JOIN term_hierarchy th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
WHERE th.parent = 1015;
于 2019-10-11T02:17:38.147 回答
0

@CodeReaper,@BennyHill:它按预期工作。

但是,我想知道表中有数百万行的时间复杂度?显然,它需要5ms执行才能在正确索引的表上拥有 5k 条记录。

我的查询:

SET status = '1'
WHERE id IN (
    SELECT id
    FROM (
      SELECT c2.id FROM clusters as c2
      WHERE c2.assign_to_user_id IS NOT NULL
        AND c2.id NOT IN (
         SELECT c1.id FROM clusters AS c1
           LEFT JOIN cluster_flags as cf on c1.last_flag_id = cf.id
           LEFT JOIN flag_types as ft on ft.id = cf.flag_type_id
         WHERE ft.slug = 'closed'
         )
      ) x)```

Or is there something we can improve on my query above?
于 2019-02-11T14:06:25.940 回答