"<>"vs"NOT IN"

DJ.*_*DJ. 20 sql sql-server sql-server-2005 sql-server-2008

我前几天调试了一个存储过程,发现了一些像这样的逻辑:

SELECT something
FROM someTable
WHERE idcode <> (SELECT ids FROM tmpIdTable)
Run Code Online (Sandbox Code Playgroud)

这没有任何回报.我认为"<>"看起来有点奇怪,所以我将其改为"NOT IN"然后一切正常.我想知道为什么会这样?这是一个非常古老的过程,我不确定该问题存在多久,但我们最近从SQL Server 2005切换到SQL Server 2008时发现了这个问题."<>"和"NOT IN"之间的真正区别是什么,并且Server2005和2008之间的行为有所改变?

Tom*_*lak 20

SELECT something
FROM someTable
WHERE idcode NOT IN (SELECT ids FROM tmpIdTable)
Run Code Online (Sandbox Code Playgroud)

检查列表中的任何值.

但是,NOT IN不是NULL容错的.如果子查询返回一组包含NULL的值,则根本不会返回任何记录.(这是因为NOT IN内部优化为idcode <> 'foo' AND idcode <> 'bar' AND idcode <> NULL等,因为任何与NULL的比较都会产生UNKNOWN,从而导致整个表达式变为TRUE.

一个更好的,容忍NULL的变体是这样的:

SELECT something
FROM someTable
WHERE NOT EXISTS (SELECT ids FROM tmpIdTable WHERE ids = someTable.idcode)
Run Code Online (Sandbox Code Playgroud)

编辑:我最初认为这个:

SELECT something
FROM someTable
WHERE idcode <> (SELECT ids FROM tmpIdTable)
Run Code Online (Sandbox Code Playgroud)

会检查第一个值.事实证明,这个假设至少对SQL Server来说是错误的,它实际上会触发他的错误:

Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

  • `WHERE idcode NOT IN (...)` 等价于 `WHERE idcode &lt;&gt; ALL (...)` (2认同)

KM.*_*KM. 13

试试这个,因为索引使用可能会运行得更快:

SELECT something
FROM someTable
    LEFT OUTER JOIN tmpIdTable ON idcode=ids
WHERE ids IS NULL
Run Code Online (Sandbox Code Playgroud)


Rob*_*Rob 8

<>是一种"单一"的NOT行动; NOT IN是一个集合操作,所以前者不起作用是有道理的.但是,我不知道它是否可以在以前版本的SQL Server下完成.


Cad*_*oux 5

当且仅当没有从tmpIdTable返回的行或单行时,此代码才有效:

SELECT something
FROM someTable
WHERE idcode <> (SELECT ids FROM tmpIdTable)
Run Code Online (Sandbox Code Playgroud)

如果返回多行,您将收到如下错误:

消息512,级别16,状态1,行1子查询返回的值超过1.当子查询跟随=,!=,<,<=,>,> =或子查询用作表达式时,不允许这样做.

这与嵌套标量获得的相同错误意外地产生多行,如:

SELECT*,(从t1 WHERE等中选择)从t2开始

在十年内,SQL Server中没有任何改变WRT这一点,所以我希望破解原始代码中嵌套查询的假设.

如果没有返回任何行,则结果将为空,因为<> NULL它永远不为真(假设为ANSI NULL).

此代码适用于任意数量的行:

SELECT something
FROM someTable
WHERE idcode NOT IN (SELECT ids FROM tmpIdTable)
Run Code Online (Sandbox Code Playgroud)

但是,仍然存在NULL问题.