Search code examples
sqlsql-serversql-server-2005sql-server-2008

"<>" vs "NOT IN"


I was debugging a stored procedure the other day and found some logic something like this:

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

This returned nothing. I thought it looked a little odd with the "<>" so I changed it to "NOT IN" and then everything worked fine. I was wondering why this is? This is a pretty old proc and I am not really sure how long the issue has been around, but we recently switched from SQL Server 2005 to SQL Server 2008 when this was discovered. What is the real difference between "<>" and "NOT IN" and has the behavior changed between Server2005 and 2008?


Solution

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

    checks against any value in the list.

    However, the NOT IN is not NULL-tolerant. If the sub-query returned a set of values that contained NULL, no records would be returned at all. (This is because internally the NOT IN is optimized to idcode <> 'foo' AND idcode <> 'bar' AND idcode <> NULL etc., which will always fail because any comparison to NULL yields UNKNOWN, preventing the whole expression from ever becoming TRUE.)

    A nicer, NULL-tolerant variant would be this:

    SELECT something
    FROM someTable
    WHERE NOT EXISTS (SELECT ids FROM tmpIdTable WHERE ids = someTable.idcode)
    

    EDIT: I initially assumed that this:

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

    would check against the first value only. It turns out that this assumption is wrong at least for SQL Server, where it actually triggers his error:

    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.