在不使用IN子句的情况下,通过T-SQL有效删除记录

时间:2018-10-09 15:39:56

标签: sql-server tsql syntax subquery

在以下情况下,是否有一种无需使用关键字IN即可从SQL Server删除记录的有效方法:

-- If Documents were deleted, remove them from your ocean
DELETE FROM IndexHistory 
WHERE DocId IN (SELECT IH.Docid 
                FROM IndexHistory IH 
                LEFT JOIN IndexedLineItems I ON IH.Docid = I.DocId
                WHERE I.Docid IS NULL)

如果您研究这种情况,则您要在圆括号内的所有查询中删除所有记录。

有记录的事实表明,使用“ IN”效率低下。因此,人们会认为应该有一种不用'IN'删除它们的方法,因为无需使用“ IN”就可以识别所有记录。

例如,我在想这样的事情是可能的,但是我没有正确的语法:

DELETE FROM IndexHistory IH 
LEFT JOIN IndexedLineItems I ON IH.Docid = I.DocId
WHERE I.Docid IS NULL

我很欣赏答案可能仍然是“不,不可能。”

如果不可能,则可能是改善Microsoft语言的建议。在我这样做之前,我想我会在这里发贴,看看我是否缺少某些东西。

4 个答案:

答案 0 :(得分:5)

出于可读性原因,我更喜欢CTE,也可以更改为使用SELECT来查看要删除的内容。这个NOT EXISTS可能也更有效:

WITH DeleteData AS
(
  SELECT IH.Docid 
  FROM IndexHistory IH 
  WHERE NOT EXISTS( SELECT 1 FROM IndexedLineItems I
                    WHERE I.DocId = IH.DocId)
)
DELETE FROM DeleteData

您不需要从此CTE到表的其他联接,因为仅选择了一个表。

答案 1 :(得分:5)

使用not exists

Delete ih from IndexHistory ih
    where not exists (select 1 from IndexedLineItems ili where ih.Docid = ili.DocId)

答案 2 :(得分:1)

换一种说法,改用内部联接,这样就只删除匹配项:

DELETE FROM IndexHistory IH 
JOIN IndexedLineItems I ON IH.Docid = I.DocId
WHERE I.Docid IS NOT NULL

答案 3 :(得分:0)

这很好...

DELETE IH
    FROM IndexHistory IH
    Left JOIN IndexedLineItems LI
      ON IH.Docid = LI.DocId
    WHERE LI.DocId is Null