代码之家  ›  专栏  ›  技术社区  ›  Adrian Grigore

删除其他表未引用的行的优雅方法

  •  34
  • Adrian Grigore  · 技术社区  · 14 年前

    我有两个表(Tasks和Timeentries),它们由外键连接(Timeentries.TaskID引用Tasks.ID)

    现在我想从任务中删除所有没有被TimeEntries表引用的行。我认为这应该管用:

    DELETE FROM Tasks WHERE ID not IN (SELECT TaskID FROM TimeEntries)
    

    但是它影响0行,即使Tasks表中有很多未引用的行。

    5 回复  |  直到 14 年前
        1
  •  56
  •   Andomar    14 年前

    有一个臭名昭著的抓到你了 not in . 基本上, id not in (1,2,3) 是指:

    id <> 1 and id <> 2 and id <> 3
    

    现在如果你的 TimeEntries 表包含具有 TaskID null 歪投球 转换为:

    ID <> null and ID <> 1 and ID <> 2 AND ...
    

    与…比较的结果 无效的 总是 unknown . 自 未知的 在SQL中不是真的 where

    一个简单的解决方法是在子查询中添加一个where子句:

    DELETE FROM Tasks 
    WHERE  ID not IN 
           (
           SELECT  TaskID 
           FROM    TimeEntries 
           WHERE   TaskID is not null
           )
    
        2
  •  24
  •   Ben Baron    7 年前

    一种方式,这将解决“问题”你有空(见下面的链接获得更多信息)

    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

        3
  •  10
  •   JohnFx    14 年前

    因为您运行的是SQL2008,所以可以使用漂亮的新合并语法。

    MERGE Tasks AS target
    USING TimeEntries as Source ON (Target.TaskID=Source.TaskID)
    WHEN NOT MATCHED BY Source THEN DELETE; 
    
        4
  •  5
  •   takrl    8 年前

    我知道这很旧,但我想知道为什么没有人提到删除查询如前所述 here . 因此,供参考:

    DELETE FROM Tasks
    FROM Tasks LEFT OUTER JOIN
        TimeEntries ON TimeEntries.TaskID = Tasks.ID
    WHERE TimeEntries.TaskID IS NULL;
    

    此语法与ISO不兼容,因此只适用于T-SQL。

        5
  •  3
  •   user125976 user125976    14 年前
      Delete FROM Tasks 
           WHERE not Exists 
              (SELECT 'X' FROM TimeEntries where TimeEntries.TaskID  = Tasks.ID)
    

    上面的SQL应该删除时间项表中Task.ID不存在的任务中的所有行。我首先将它作为select语句运行以测试:)