我有两个表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”消息
答案 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如何处理加入 - 删除,但我想它应该以相同的方式工作。