SQL中"IF EXISTS"和"IF NOT EXISTS"有什么区别?

8

我很新手SQL。我想知道在使用“IF EXISTS”或“IF NOT EXISTS”时会发生什么。 例如:以下两个语句有什么区别:

语句1:(EXISTS)

IF EXISTS( SELECT ORDER_ID FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032 )
BEGIN
     DELETE FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032
END

Statement 2: (NOT EXISTS)

IF NOT EXISTS( SELECT ORDER_ID FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032 )
BEGIN
     DELETE FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032
END

IF EXISTSIF NOT EXISTS会返回什么?这两者哪一个更好? 何时使用IF EXISTS,何时使用IF NOT EXISTS

7个回答

4

这里有4个示例,说明了何时使用IF EXISTS和何时使用IF NOT EXISTS:

A)从多个表中删除相关记录:-

IF EXISTS (SELECT TOP(1) 1 FROM Table1 WHERE ORDER_ID = 11032) BEGIN
    DELETE FROM Table1 WHERE ORDER_ID = 11032
    DELETE FROM Table2 WHERE ORDER_ID = 11032
    -- possibly more statements following here ...
END

B) 如果存在,则在多张表中更新记录:

IF EXISTS (SELECT TOP(1) 1 FROM Table1 WHERE ORDER_ID = 11032) BEGIN
    UPDATE Table1 SET Field1='X' WHERE ORDER_ID = 11032
    UPDATE Table2 SET Field2='Y' WHERE ORDER_ID = 11032
    -- possibly more statements following here ...
END

C)如果记录不存在,请在多个表中插入记录:

IF NOT EXISTS (SELECT TOP(1) 1 FROM Table1 WHERE ORDER_ID = 11032) BEGIN
    INSERT INTO Table1(Field1, Field2, ORDER_ID) VALUES ('A', 'B', 11032)
    INSERT INTO Table2(Field3, Field4, ORDER_ID) VALUES ('X', 'Y', 11032)
    -- possibly more statements following here ...
END

D) 根据记录的存在与否,进行插入或更新操作。
IF EXISTS (SELECT TOP(1) 1 FROM Table1 WHERE ORDER_ID = 11032) BEGIN
    UPDATE Table1 SET Field1='X' WHERE ORDER_ID = 11032
    -- possibly more statements following here ...
END
ELSE BEGIN
    INSERT INTO Table1(Field1, Field2, ORDER_ID) VALUES ('X', 'B', 11032)
    -- possibly more statements following here ...
END

除了上述陈述(案例D)外,您还可以使用新的MERGE语句,但我认为它有点复杂。

注意事项:

  • 如果只有一个表受影响,您在上面的任何示例中都不会使用EXIST,除非在upsert示例D)中。
  • SELECT TOP(1) 1 FROM ...更有效,因为它在找到第一个匹配项后中止,然后仅返回数字1(这比选择例如NVARCHAR(max)字段更有效)
  • 您可以看到只有在示例C)中,您被迫使用IF NOT EXISTS(...),所有其他示例都使用IF EXISTS(...)这更有效。

2
如果有order_id等于11032的order_details,你的第一个语句将会运行:
DELETE FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032

如果没有order_id等于11032的order_details,则会运行你的第二个语句。请注意,这是一个空集,因为您只是检查了是否有该order_id的订单。
实际上,在这个例子中,只运行DELETE会更容易 - IF EXISTS和IF NOT EXISTS是多余的。

2
< p > IF EXISTS检查结果集不为空,而IF NOT EXISTS检查结果集为空

这两者中哪一个更好?

给你适当的语义的那个更好。

什么时候使用"IF EXISTS",什么时候使用"IF NOT EXISTS"

当您需要检查结果集的非空或空时使用。


1
伙计,我不明白短语“.....checks that the result set is not not empty so empty.....”的意思。 - carolene

2

你需要第一个语句。基本上,“IF EXISTS” 返回真值,如果查询返回 1 行或更多行,所以在你的例子中它会返回一行(包含一个值为 1 的字段),因此将执行你想要的删除语句。


1
如果您想要在某个地方插入一些内容,而该内容不存在,则第二种方法更为适合。例如: IF NOT EXISTS( SELECT 1 FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032 ) BEGIN INSERT INTO DBO.ORDER_DETAILS (... some values) END - Mark Robinson

2

这两个语句都会返回一个布尔值的真/假结果。

EXISTS 如果结果集不为空,则返回true。

NOT EXISTS 是一个否定操作,如果结果集为空,则返回true。


@carolene:首要的是哪一个语义是正确的。 - jason
性能方面它们会很相似,如果有任何不存在的情况,可能会稍微慢一些,因为它会否定EXISTS的结果。 - Mitchel Sellers
如果不存在任何东西,可能会稍微慢一些,因为它否定了EXISTS的结果。我认为情况恰恰相反。EXISTSNOT EXISTS都可以进行短路操作。数据元素名ORDER_ID表明具有良好的选择性,当找到一个不匹配搜索条件ORDER_ID = 11032的值时,NOT EXISTS将评估为FALSE(短路),很可能是遇到的第一个值。而EXISTS在找到与搜索条件匹配的值之前不会返回TRUE(短路),这可能需要搜索许多订单才能找到。 - onedaywhen

1

这绝对是使用EXISTS的一种方式。但我不确定第二个会有任何作用。

然而,你可以只需

DELETE FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032

并且完全删除 EXISTS,除非你想执行

IF EXISTS ( SELECT ORDER_ID FROM ORDERS WHERE ORDER_ID = 11032 ) BEGIN
     DELETE FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032
     DELETE FROM DBO.ORDERS WHERE ORDER_ID = 11032
END

或者你的实际代码比展示的更加复杂。

你的第二个语句永远不会删除任何东西,因为如果有行存在,它将评估为FALSE,并且不执行DELETE。如果没有行存在,它将评估为TRUE并执行DELETE,但由于没有行存在,因此不会执行任何操作。

就性能而言,在你使用EXISTS的上下文中,无论哪种方法都没有更好的性能,因为它只是评估从SELECT得到的结果集是否为NULL

EXISTS 还有另一种用法,其中 NOT EXISTSEXISTS 效率要低得多,并且可以被更有效的短语替换。我指的是当您在语句的 WHERE 子句中使用 NOT EXISTS 时。在这种情况下,您最好执行一个 LEFT JOIN(而不是您可能拥有的 INNER JOIN),并过滤 WHERE rightTable.SomeColumn IS NULL


伙计,我正在尝试优化一个存储过程,所以在删除记录之前,我需要使用“IF EXISTS”或“IF NOT EXISTS”条件。 - carolene
为什么优化需要使用EXISTS?优化是减少总体复杂度,而您展示的代码增加了工作量而没有原因。当然,除非您的实际代码更复杂。 - Brad

1

"EXISTS简单地测试内部查询是否返回任何行。如果是,则外部查询继续执行。如果不是,则外部查询不执行,并且整个SQL语句不返回任何内容。"请参见此处。NOT EXISTS当然是EXISTS的否定。

第一个语句的作用是,如果可以找到订单,它将发出DELETE查询。第二个语句没有任何意义,因为它会在订单不存在时发出查询。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接