2010-12-17 80 views
59

我试图做一个查询这样的:MySQL的DELETE FROM与子查询的条件

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

+1

**注意**:好的答案在底部http://stackoverflow.com/a/4471359/956397只需在DELETE t FROM table t之后添加表别名...' – PiTheNumber 2014-07-24 10:06:32

回答

28

您不能指定目标表删除。

一种解决方法

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

我们都是对的 - 请参阅他的评论以下我的答案。别名的语法和逻辑都是问题:) – JNK 2010-12-17 14:51:27

+0

是啊,似乎通过子查询删除目前在MySQL中是不可能的 - 感谢您看看它:) – mikl 2010-12-17 14:51:44

+0

不会在最后一行中的“DELETE FROM term_hierarchy AS th”具有同样的问题?我得到的语法错误与OP相同。 – malhal 2012-01-24 20:02:55

6

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

DELETE th FROM term_hierarchy AS th 
.... 

As outlined here in MySQL docs.

+0

不是别名,请再次检查OP – ajreal 2010-12-17 14:24:20

+0

@ajreal - 我做过了,请注意错误从别名定义开始,并且MySQL文档明确声明您需要在DELETE语句以及FROM子句中使用别名。尽管感谢downvote。 – JNK 2010-12-17 14:25:19

+0

只要做到这一点'从你的表中删除你的表t1,其中t1.id in(从your_table t2选择t2.id);'你得到了什么? – ajreal 2010-12-17 14:27:14

30

别名应包含在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 
); 
+2

这是一个很好的答案。适当的别名将大大解决类似于原始帖子的问题。 (像我的。) – usumoio 2013-12-04 21:02:33

188

对于其他人发现这个问题看,同时使用子查询,删除,我离开你这个例子超过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会很乐意做你所要求的。

+7

花了一些时间,但我得到它的工作。重要说明:1)第一个表必须如此处所示的别名为“e”,2)末尾的“x”不是占位符,它是由子查询生成的临时表的别名“(SELECT id FROM tableE WHERE arg = 1 AND foo ='bar')“。 – 2013-03-08 11:28:26

+3

这是为什么工作?这对我来说有很大的改变,但是,它不应该起作用。它*做*工作,但它不应该。 – donatJ 2014-04-14 21:53:07

+1

令人难以置信。这实际上有效!但是你不会被迫使用e来替换表...你可以使用任何你想要的别名。 – 2014-04-29 13:37:00

4

我以一种稍微不同的方式接近这个,它对我有用;

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

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

适合我。

3

是不是删除中的“in”子句...如果从子查询中返回大量的值,效率极低?不知道为什么你不会为了删除而不是内部(或右边)从子查询中反向删除原始表,而不是我们的“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不允许它”,但是,它工作正常,我提供的我一定要完全弄清楚删除的内容(DELETE FROM牛逼目标AS T)。 Delete with Join in MySQL阐明DELETE/JOIN问题。

0

如果你想与2个查询要做到这一点,你总是可以做同样的事情到这一点:

1)抓住IDS从表:

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

然后复制用鼠标/键盘导致或编程语言为XXX:

2) DELETE FROM your_table WHERE id IN (XXX) 

也许你可以在一个查询中做到这一点,但这是我更喜欢的。