Why does NULL = NULL evaluate to false in SQL server

前端 未结 19 1560
一向
一向 2020-11-22 05:02

In SQL server if you have nullParam=NULL in a where clause, it always evaluates to false. This is counterintuitive and has caused me many errors. I do understa

相关标签:
19条回答
  • 2020-11-22 05:45

    The answers here all seem to come from a CS perspective so I want to add one from a developer perspective.

    For a developer NULL is very useful. The answers here say NULL means unknown, and maybe in CS theory that's true, don't remember, it's been a while. In actual development though, at least in my experience, that happens about 1% of the time. The other 99% it is used for cases where the value is not UNKNOWN but it is KNOWN TO BE ABSENT.

    For example:

    • Client.LastPurchase, for a new client. It is not unknown, it is known that he hasn't made a purchase yet.

    • When using an ORM with a Table per Class Hierarchy mapping, some values are just not mapped for certain classes.

    • When mapping a tree structure a root will usually have Parent = NULL

    • And many more...

    I'm sure most developers at some point wrote WHERE value = NULL, didn't get any results, and that's how they learned about IS NULL syntax. Just look how many votes this question and the linked ones have.

    SQL Databases are a tool, and they should be designed the way which is easiest for their users to understand.

    0 讨论(0)
  • 2020-11-22 05:46

    Maybe it depends, but I thought NULL=NULL evaluates to NULL like most operations with NULL as an operand.

    0 讨论(0)
  • 2020-11-22 05:46

    null is unknown in sql so we cant expect two unknowns to be same.

    However you can get that behavior by setting ANSI_NULLS to Off(its On by Default) You will be able to use = operator for nulls

    SET ANSI_NULLS off
    if null=null
    print 1
    else 
    print 2
    set ansi_nulls on
    if null=null
    print 1
    else 
    print 2
    
    0 讨论(0)
  • 2020-11-22 05:49

    At technet there is a good explanation for how null values work.

    Null means unknown.

    Therefore the Boolean expression

    value=null

    does not evaluate to false, it evaluates to null, but if that is the final result of a where clause, then nothing is returned. That is a practical way to do it, since returning null would be difficult to conceive.

    It is interesting and very important to understand the following:

    If in a query we have

    where (value=@param Or @param is null) And id=@anotherParam
    

    and

    • value=1
    • @param is null
    • id=123
    • @anotherParam=123

    then

    "value=@param" evaluates to null
    "@param is null" evaluates to true
    "id=@anotherParam" evaluates to true

    So the expression to be evaluated becomes

    (null Or true) And true

    We might be tempted to think that here "null Or true" will be evaluated to null and thus the whole expression becomes null and the row will not be returned.

    This is not so. Why?

    Because "null Or true" evaluates to true, which is very logical, since if one operand is true with the Or-operator, then no matter the value of the other operand, the operation will return true. Thus it does not matter that the other operand is unknown (null).

    So we finally have true=true and thus the row will be returned.

    Note: with the same crystal clear logic that "null Or true" evaluates to true, "null And true" evaluates to null.

    Update:
    Ok, just to make it complete I want to add the rest here too which turns out quite fun in relation to the above.

    "null Or false" evaluates to null, "null And false" evaluates to false. :)

    The logic is of course still as self-evident as before.

    0 讨论(0)
  • 2020-11-22 05:51

    The confusion arises from the level of indirection (abstraction) that comes about from using NULL.

    Going back to the "what's under the Christmas tree" analogy, "Unknown" describes the state of knowledge about what is in Box A.

    So if you don't know what's in Box A, you say it's "Unknown", but that doesn't mean that "Unknown" is inside the box. Something other than unknown is in the box, possibly some kind of object, or possibly nothing is in the box.

    Similarly, if you don't know what's in Box B, you can label your state of knowledge about the contents as being "Unknown".

    So here's the kicker: Your state of knowledge about Box A is equal to your state of knowledge about Box B. (Your state of knowledge in both cases is "Unknown" or "I don't know what's in the Box".) But the contents of the boxes may or may not be equal.

    Going back to SQL, ideally you should only be able to compare values when you know what they are. Unfortunately, the label that describes a lack of knowledge is stored in the cell itself, so we're tempted to use it as a value. But we should not use that as a value, because it would lead to "the content of Box A equals the content of Box B when we don't know what's in Box A and/or we don't know what's in Box B. (Logically, the implication "if I don't know what's in Box A and if I don't know what's in Box B, then what's in Box A = What's in Box B" is false.)

    Yay, Dead Horse.

    0 讨论(0)
  • 2020-11-22 05:53

    The equality test, for example, in a case statement when clause, can be changed from

    XYZ = NULL 
    

    to

    XYZ IS NULL
    

    If I want to treat blanks and empty string as equal to NULL I often also use an equality test like:

    (NULLIF(ltrim( XYZ ),'') IS NULL)
    
    0 讨论(0)
提交回复
热议问题