“<>” vs “NOT IN”

后端 未结 9 1463
Happy的楠姐
Happy的楠姐 2020-12-14 17:53

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

SELECT something
FROM someTable
WHERE idcode <> (SELECT ids          


        
相关标签:
9条回答
  • 2020-12-14 17:57

    <> is essentially "nor"

    on SQL WHERE NOT demo I tried the following

    FAILS:

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

    WORKS

    WHERE NOT Country='Mexico' AND country<>'Sweden'
    
    0 讨论(0)
  • 2020-12-14 18:02

    I have no idea why would you write something like WHERE idcode <> (SELECT ids FROM tmpIdTable). A SELECT statement will return a set of tuples and your idcode either will or will NOT be IN this set. "WHERE idcode NOT IN (SELECT ids FROM tmpIdTable)" is the way to do it.

    0 讨论(0)
  • 2020-12-14 18:04

    This code is valid if and only if there are no rows or a single row returned from tmpIdTable:

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

    If multiple rows are returned, you will get an error like:

    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.

    This is the same error you get with nested scalar unexpectedly produces multiple rows like:

    SELECT *, (SELECT blah FROM t1 WHERE etc.) FROM t2

    Nothing has changed WRT this in SQL Server in a decade, so I expect assumptions about the nested query in the original code have been broken.

    If no rows are returned, the result will be empty since <> NULL is never true (assume ANSI NULLs).

    This code is valid for any number of rows:

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

    However, there still can be issues with NULL.

    0 讨论(0)
  • 2020-12-14 18:05

    If the SELECT subquery returns zero rows, that's a NULL. When NULL is compared to anything, the result is always UNKNOWN, and never TRUE. Confusingly enough, NOT UNKNOWN is equal to UNKNOWN.

    I avoid three valued logic (TRUE, FALSE, UNKNOWN) whenever possible. It's not that hard to avoid once you get the hang of it.

    If the SELECT subquery returns exactly one value, the comparison for inequality should return the result you expect.

    If the SELECT subquery returns more than one value, you should get an error.

    In general, NOT IN will return the result you expect when you are testing for non membership in a set.

    This response overlaps other responses, but it's phrased a little differently.

    Edited to add more detail about NOT IN:

    I did some searching about NOT IN in Oracle, and I learned something I didn't know a half an hour ago. NOT IN is NULL sensitive. In particular,

    X NOT IN (SELECT ...)
    

    Is not the same as

    NOT (X IN SELECT ...))
    

    I may have to amend my earlier response!

    0 讨论(0)
  • 2020-12-14 18:07

    try this, may run faster because of index usage:

    SELECT something
    FROM someTable
        LEFT OUTER JOIN tmpIdTable ON idcode=ids
    WHERE ids IS NULL
    
    0 讨论(0)
  • 2020-12-14 18:08

    queries using NOT IN may be brittle:

    http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/10/21/defensive-database-programming-rewriting-queries-with-not-in.aspx

    0 讨论(0)
提交回复
热议问题