“<>” 中vs“NOT IN”

时间:2009-05-13 14:38:30

标签: sql sql-server sql-server-2005 sql-server-2008

我前几天正在调试存储过程,并发现了类似这样的逻辑:

SELECT something
FROM someTable
WHERE idcode <> (SELECT ids FROM tmpIdTable)

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

9 个答案:

答案 0 :(得分:20)

SELECT something
FROM someTable
WHERE idcode NOT IN (SELECT ids FROM tmpIdTable)

检查列表中的任何值。

但是,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)

编辑:我最初认为这是:

SELECT something
FROM someTable
WHERE idcode <> (SELECT ids FROM tmpIdTable)

只会检查第一个值。事实证明,这种假设至少对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.

答案 1 :(得分:13)

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

SELECT something
FROM someTable
    LEFT OUTER JOIN tmpIdTable ON idcode=ids
WHERE ids IS NULL

答案 2 :(得分:8)

<>是一个“单数”NOT操作; NOT IN是一个集合操作,因此前者不起作用是有道理的。但是,我不知道它是否可以在以前版本的SQL Server下完成。

答案 3 :(得分:5)

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

SELECT something
FROM someTable
WHERE idcode <> (SELECT ids FROM tmpIdTable)

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

Msg 512,Level 16,State 1,Line 1 子查询返回的值超过1。当子查询遵循=,!=,&lt;,&lt; =,&gt;,&gt; =或子查询用作表达式时,不允许这样做。

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

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

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

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

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

SELECT something
FROM someTable
WHERE idcode NOT IN (SELECT ids FROM tmpIdTable)

但是,仍然存在NULL问题。

答案 4 :(得分:3)

我不知道为什么你会写WHERE idcode <> (SELECT ids FROM tmpIdTable)之类的东西。 SELECT语句将返回一组元组,并且您的idcode将会或不会在此集合中。 “WHERE idcode NOT IN (SELECT ids FROM tmpIdTable)”就是这样做的方式。

答案 5 :(得分:3)

如果SELECT子查询返回零行,则为NULL。将NULL与任何内容进行比较时,结果始终为UNKNOWN,并且永远不为TRUE。令人困惑的是,NOT UNKNOWN等于UNKNOWN。

尽可能避免使用三值逻辑(TRUE,FALSE,UNKNOWN)。一旦掌握了它,就不难避免。

如果SELECT子查询只返回一个值,则不等式的比较应返回您期望的结果。

如果SELECT子查询返回多个值,则应该出错。

通常,NOT IN将返回您在测试集合中的非成员资格时所期望的结果。

这种回应与其他回复重叠,但措辞略有不同。

编辑以添加有关NOT IN的更多详细信息:

我在Oracle中搜索了一些NOT IN,并且我在半小时前学到了一些我不知道的东西。 NOT IN是NULL敏感的。特别是,

X NOT IN (SELECT ...)

不一样
NOT (X IN SELECT ...))

我可能需要修改我之前的回复!

答案 6 :(得分:2)

答案 7 :(得分:-1)

在某些版本的SQL != 中应该用于“not equals”逻辑语句。 你试过了吗?

答案 8 :(得分:-1)

<>本质上是“不”

SQL WHERE NOT demo上,我尝试了以下操作

失败:

WHERE NOT Country='Mexico' AND WHERE NOT country ='Sweden'

作品

WHERE NOT Country='Mexico' AND country<>'Sweden'