![](/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.