[英]MySQL DELETE FROM with subquery as condition
我正在尝试进行这样的查询:
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 不允许您删除的表用于条件的子查询。
对于在使用子查询时发现这个问题想要删除的其他人,我给你留下了这个例子来超越 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
);
您不能指定要删除的目标表。
解决方法
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);
我以稍微不同的方式处理这个问题,它对我有用;
我需要从我的表中删除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`
)
为我工作。
如果子查询返回大量值,delete 中的“in”子句不是非常低效吗? 不知道为什么你不只是inner(或right)从子查询上的原始表中加入要删除的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 问题。
如果你想用 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 )
也许你可以在一个查询中做到这一点,但这是我更喜欢的。
@CodeReaper、@BennyHill:它按预期工作。
但是,我想知道表中有数百万行的时间复杂度? 显然,在正确索引的表上执行 5k 条记录需要大约 5 5ms
。
我的查询:
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?
您可以在删除语句中以这种方式使用别名
DELETE th.*
FROM term_hierarchy th
INNER JOIN term_hierarchy th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
WHERE th.parent = 1015;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.