[英]How do I delete all the records in a table that have corresponding records in another table
I have two tables A and B. I would like to delete all the records from table A that are returned in the following query: 我有两个表A和B.我想删除在以下查询中返回的表A中的所有记录:
SELECT A.*
FROM A , B
WHERE A.id = B.a_id AND
b.date < '2008-10-10'
I have tried: 我努力了:
DELETE A
WHERE id in (
SELECT a_id
FROM B
WHERE date < '2008-10-10')
but that only works if the inner select actually returns a value (not if the result set is empty) 但这只有在内部选择实际返回一个值时才有效(如果结果集为空则不行)
NB: this has to work on both SQLServer AND MySQL 注意:这必须适用于SQLServer和MySQL
EDIT: More information 编辑:更多信息
The above delete works 100% on SQLServer 以上删除在SQLServer上100%有效
When running it on MySQL I get an "error in you SQL syntax" message which points to the start of the SELECT as the problem. 在MySQL上运行时,我得到一个“SQL语法错误”消息,指出SELECT的开始是问题。 if I substitute the inner select with (1,2) then it works.
如果我用(1,2)替换内部选择,那么它的工作原理。
@Kibbee You are right it actually makes no difference if the inner select returns rows or not. @Kibbee你是对的,如果内部选择返回行,它实际上没有区别。
@Fred I get a "not unique table.alias: a" message @Fred我得到一个“不唯一的table.alias:a”消息
I think this should work (works on MySQL anyway): 我认为这应该有效(无论如何都适用于MySQL):
DELETE a.* FROM A a JOIN B b ON b.id = a.id WHERE b.date < '2008-10-10';
Without aliases: 没有别名:
DELETE A.* FROM A JOIN B ON B.id = A.id WHERE B.date < '2008-10-10';
I'm not sure why your method is failing. 我不确定你的方法失败的原因。 If the inner query returns an empty set, then the first query should also return an empty set.
如果内部查询返回空集,则第一个查询也应返回空集。 I don't think @Fred's solution is right, as he seems to be joining on the wrong column.
我不认为@Fred的解决方案是正确的,因为他似乎加入了错误的专栏。
Or you could switch to an exists syntax with a correlated subquery ... 或者您可以切换到具有相关子查询的存在语法...
Delete A
From A
Where Exists
(Select * From B
Where B.Id = A.Id
And B.date < '2008-10-10');
Depending on how smart the query optimizer is, (and how many records in Table B would be returned by the subquery) this could be faster, as an exists doesn't need to completely generate the full resultset... It can stop as soon as it finds one record... 根据查询优化器的智能程度,(以及子查询将返回表B中的记录数),这可能会更快,因为存在不需要完全生成完整的结果集...它可以尽快停止因为它找到了一条记录......
You were not so far from the answer! 你离答案还不远!
Post Edited: Remove alias on table A and B 发布后:删除表A和B上的别名
DELETE FROM A
WHERE A.id in (
SELECT B.a_id
FROM B
WHERE B.date < '2008-10-10');
You could also use ON CASCADE in your child table so that when a row is deleted in your parent table it automatically deletes child rows in the child table. 您还可以在子表中使用ON CASCADE,以便在父表中删除行时,它会自动删除子表中的子行。 In that way you need not worry about referential integrity when a parent row is deleted.
这样,删除父行时无需担心引用完整性。
delete from a inner join b on a.id = b.a_id and b.date < '2008-10-10'
Another option in MYSQL and MSSQL, but its long way round of doing it: 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
According to your description to your DELETE-statement, you want to delete empty orphants in table A aswell? 根据你对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
(please note the inverted way of joining in B) (请注意B中倒入的倒入方式)
Should do the trick in that case. 在这种情况下应该做的伎俩。 I'm not sure how MSSQL deals with join-deletes, but I guess that it should work the same way.
我不确定MSSQL如何处理加入 - 删除,但我想它应该以相同的方式工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.