我有两个表(Tasks和Timeentries),它们通过外键连接(TimeEntries.TaskID引用Tasks.ID)
现在,我想删除任务中未被TimeEntries表引用的所有行。我认为这应该有效:
DELETE FROM Tasks WHERE ID not IN (SELECT TaskID FROM TimeEntries)
但它会影响0行,即使Tasks表中有很多未引用的行。
这可能是什么问题?当然我可以写一个迭代所有行的SP,但看起来这可以在一个衬里完成。
我猜这是睡眠时间下溢错误之一。请帮忙!
答案 0 :(得分:51)
not in
有一个臭名昭着的陷阱。基本上,id not in (1,2,3)
是简写:
id <> 1 and id <> 2 and id <> 3
现在,如果您的TimeEntries
表包含TaskID
null
的任何行,则not in
会转换为:
ID <> null and ID <> 1 and ID <> 2 AND ...
与null
进行比较的结果始终为unknown
。由于unknown
在SQL中不正确,where
子句会过滤掉所有行,并且最终不会删除任何行。
一个简单的修复是子查询中的附加where子句:
DELETE FROM Tasks
WHERE ID not IN
(
SELECT TaskID
FROM TimeEntries
WHERE TaskID is not null
)
答案 1 :(得分:20)
一种方法,这将解决您使用空值的“问题”(请参阅下面的链接了解更多信息)
DELETE FROM Tasks
WHERE NOT EXISTS (SELECT 1 FROM TimeEntries
WHERE TimeEntries.TaskID = Tasks.ID )
要了解您遇到的问题,请查看Select all rows from one table that don't exist in another table
答案 2 :(得分:9)
由于您运行的是SQL 2008,因此可以使用漂亮的新合并语法。
MERGE Tasks AS target
USING TimeEntries as Source ON (Target.TaskID=Source.TaskID)
WHEN NOT MATCHED BY Source THEN DELETE;
答案 3 :(得分:4)
答案 4 :(得分:3)
Delete FROM Tasks
WHERE not Exists
(SELECT 'X' FROM TimeEntries where TimeEntries.TaskID = Tasks.ID)
SQL Above应删除任务中所有行,其中Task.ID在时间条目表中不存在。我会首先将它作为select语句运行来测试:)