如何删除表中具有另一个表中相应记录的所有记录

时间:2008-11-07 13:23:49

标签: sql mysql sql-server

我有两个表A和B.我想删除表A中所有在以下查询中返回的记录:

SELECT A.*
FROM A , B
WHERE A.id = B.a_id AND
    b.date < '2008-10-10'

我试过了:

DELETE A 
WHERE id in (
    SELECT a_id 
    FROM B 
    WHERE date < '2008-10-10')

但仅当内部选择实际返回一个值时才有效(如果结果集为空,则无效)

NB:这必须适用于 SQLServer和MySQL

编辑:更多信息

以上删除在SQLServer

上100%有效

在MySQL上运行时,我收到“SQL语法错误”消息,指出SELECT的开头是问题。如果我用(1,2)替换内部选择,那么它的工作原理。

@Kibbee你是对的,如果内部选择返回行,它实际上没有区别。

@Fred我得到一个“不唯一的table.alias:a”消息

8 个答案:

答案 0 :(得分:5)

我认为这应该有效(无论如何都适用于MySQL):

DELETE a.* FROM A a JOIN B b ON b.id = a.id WHERE b.date < '2008-10-10';

没有别名:

DELETE A.* FROM A JOIN B ON B.id = A.id WHERE B.date < '2008-10-10';

答案 1 :(得分:3)

我不确定你的方法失败的原因。如果内部查询返回空集,则第一个查询也应返回空集。我不认为@ Fred的解决方案是正确的,因为他似乎加入了错误的专栏。

答案 2 :(得分:2)

或者您可以切换到具有相关子查询的存在语法...

Delete A 
From A
Where Exists 
      (Select * From B 
       Where B.Id = A.Id
         And B.date < '2008-10-10');

根据查询优化器的智能程度,(以及子查询返回表B中的记录数),这可能会更快,因为存在不需要完全生成完整的结果集...它可以一找到一条记录就停止......

答案 3 :(得分:1)

你离答案还不远!

发布后编辑:删除表A和B上的别名

DELETE FROM A
WHERE A.id in (
    SELECT B.a_id 
    FROM B
    WHERE B.date < '2008-10-10');

答案 4 :(得分:1)

您还可以在子表中使用ON CASCADE,以便在父表中删除行时,它会自动删除子表中的子行。这样,在删除父行时,您无需担心参照完整性。

答案 5 :(得分:0)

delete from a inner join b on a.id = b.a_id and b.date < '2008-10-10'

答案 6 :(得分:0)

MYSQL和MSSQL中的另一个选项,但它还有很长的路要走:

select b.ID
into #T
from 
    [Table b] with (nolock) 
where 
  b.date > '2008-10-10'

if exists (select * from #T with (nolock))
    delete from [Table a] where a.id in (select id from #T with (nolock))
    drop table #T

答案 7 :(得分:-1)

根据你对DELETE语句的描述,你想删除表A中的空的orphants吗?

DELETE A.*
FROM A 
LEFT JOIN B ON A.id = B.a_id AND b.date > '2008-10-10'
WHERE b.id IS NULL

(请注意加入B的倒置方式)

在这种情况下应该做的伎俩。我不确定MSSQL如何处理加入 - 删除,但我想它应该以相同的方式工作。