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.
KM.*_*KM. 13
试试这个,因为索引使用可能会运行得更快:
SELECT something
FROM someTable
LEFT OUTER JOIN tmpIdTable ON idcode=ids
WHERE ids IS NULL
Run Code Online (Sandbox Code Playgroud)
当且仅当没有从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问题.