![](/img/trans.png)
[英]How do I only select records in a table that have all the values from another table?
[英]How do I delete all the records in a table that have corresponding records in another table
我有两个表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')
但这只有在内部选择实际返回一个值时才有效(如果结果集为空则不行)
注意:这必须适用于SQLServer和MySQL
编辑:更多信息
以上删除在SQLServer上100%有效
在MySQL上运行时,我得到一个“SQL语法错误”消息,指出SELECT的开始是问题。 如果我用(1,2)替换内部选择,那么它的工作原理。
@Kibbee你是对的,如果内部选择返回行,它实际上没有区别。
@Fred我得到一个“不唯一的table.alias:a”消息
我认为这应该有效(无论如何都适用于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';
我不确定你的方法失败的原因。 如果内部查询返回空集,则第一个查询也应返回空集。 我不认为@Fred的解决方案是正确的,因为他似乎加入了错误的专栏。
或者您可以切换到具有相关子查询的存在语法...
Delete A
From A
Where Exists
(Select * From B
Where B.Id = A.Id
And B.date < '2008-10-10');
根据查询优化器的智能程度,(以及子查询将返回表B中的记录数),这可能会更快,因为存在不需要完全生成完整的结果集...它可以尽快停止因为它找到了一条记录......
你离答案还不远!
发布后:删除表A和B上的别名
DELETE FROM A
WHERE A.id in (
SELECT B.a_id
FROM B
WHERE B.date < '2008-10-10');
您还可以在子表中使用ON CASCADE,以便在父表中删除行时,它会自动删除子表中的子行。 这样,删除父行时无需担心引用完整性。
delete from a inner join b on a.id = b.a_id and b.date < '2008-10-10'
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
根据你对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如何处理加入 - 删除,但我想它应该以相同的方式工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.