MySQL 如何解决错误 1093

4

错误1093表示,如果您的子查询查询您正在删除的表,则无法使用子查询进行UPDATE或DELETE。

因此,您不能执行以下操作:

delete from table1 where id in (select something from table1 where condition) ;

好的,如果你确实需要子查询来执行删除操作且无法完全消除自引用子查询,那么绕过此限制的最佳方法是什么?(假设你确实需要子查询)
编辑:
对于那些感兴趣的人,以下是查询语句:
mysql> desc adjacencies ; +---------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+---------+------+-----+---------+-------+ | parent | int(11) | NO | PRI | NULL | | | child | int(11) | NO | PRI | NULL | | | pathLen | int(11) | NO | | NULL | | +---------+---------+------+-----+---------+-------+
-- 该查询将要求我所有的孩子停止认为我的旧父母仍然是他们的父母
delete from adjacencies where parent in ( -- 所有我的父母,祖父母等等 select parent from adjacencies where child=@me and parent!=@me )
-- 只关注我的祖父母与孙子女之间的关系 and child in ( -- 获取我所有的孩子 select child from adjacencies where parent=@me );
所以,到目前为止我尝试的方法是创建一个名为adjsToDelete的临时表。
create temporary table adjsToRemove( parent int, child int ) ;
insert into adjsToRemove...

现在我有一系列需要删除的关系,其中每个父/子对都唯一地标识了要删除的行。但是,我如何从相邻表中删除每个呢?

看来我需要为adjacencies中的每个条目添加一个唯一的auto_increment键,对吗?


你尝试过使用 nolock 吗? - Stefan H
你想做什么?查询是什么? - Pentium10
a1ex07的答案(使用join删除)在大表上的性能比使用双重嵌套子查询的解决方法更好。 - Kip
6个回答

8

http://bugs.mysql.com/bug.php?id=6980中发现的一种解决方法(对我有效),是创建一个别名来引用将返回项的子查询。因此:

delete from table1 where id in 
  (select something from table1 where condition)

将被更改为

delete from table1 where id in
  (select p.id from (select something from table1 where condition) as p)

2
你可以做:

delete t1,t2 
FROM  table1 t1  
INNER JOIN 
table1 t2 ON (t2.something = t1.id);

对于问题中的查询,以下内容应该是等效的:

delete A
from adjacencies A
join adjacencies B ON A.parent = B.parent AND B.child=@me AND B.parent != @me
join adjacencies C ON A.child = C.child AND C.parent=@me

你可以在删除操作中使用内连接。 - Pentium10
有人能澄清一下如何使用此响应来执行问题中列出的子查询吗? - bobobobo
未经测试,但类似于 DELETE a1 FROM adjacencies AS a1 INNER JOIN adjacencies AS a2 ON a1.id=a2.id WHERE a1.parent=a2.parent and a2.child=@me and a2.parent!=@me; - Pentium10
@a1ex07 我已经更新了一个(未经测试的)示例,展示了如何解决原始查询。 - Kip

1

简化:

-- Collect ids
CREATE TEMPORARY TABLE cleanup_lookup AS 
SELECT id FROM table1 WHERE condition;

-- Delete the selected records
DELETE t FROM table1 t INNER JOIN cleanup_lookup l ON t.id = l.id;

-- Temporary tables get dropped when the connection is closed.

1

看起来我需要在我的邻接表中添加一个ID列,就像这样:create table adjacencies( id int PRIMARY KEY, parent int, child int, pathLen int ) -- 如果没有这个解决方案,我就做不了这个任务,对吧? - bobobobo
@bobobobo - 是的,您可以创建一个额外的列,并将其更新为与匹配ID相同的ID,如果额外列包含非零值,则删除它。 或者创建一个快照表包含所有ID。我更喜欢第二种方法,因为它不会影响当前正在工作的数据。 - ajreal

0

你可以毫不犹豫地使用这个。

你的查询:

delete from table1 
where id in (select something from table1 where condition);

更新的查询:

DELETE FROM table1 
WHERE id IN (SELECT * 
             FROM 
                 (SELECT MIN(id) FROM table1 GROUP BY Column2) x);

这里的Column2是您想要查找重复记录的列。


0
DELETE FROM `table1` 
WHERE id IN (SELECT * 
             FROM 
                 (select max(`id`)FROM table1 group by Column2 having count(*) >1) x);

这里的Column2是您想要查找重复记录的列(它可能有多个列)。

这将仅删除重复记录。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接