Why does NULL = NULL evaluate to false in SQL server

前端 未结 19 1874
一向
一向 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:32

    The concept of NULL is questionable, to say the least. Codd introduced the relational model and the concept of NULL in context (and went on to propose more than one kind of NULL!) However, relational theory has evolved since Codd's original writings: some of his proposals have since been dropped (e.g. primary key) and others never caught on (e.g. theta operators). In modern relational theory (truly relational theory, I should stress) NULL simply does not exist. See The Third Manifesto. http://www.thethirdmanifesto.com/

    The SQL language suffers the problem of backwards compatibility. NULL found its way into SQL and we are stuck with it. Arguably, the implementation of NULL in SQL is flawed (SQL Server's implementation makes things even more complicated due to its ANSI_NULLS option).

    I recommend avoiding the use of NULLable columns in base tables.


    Although perhaps I shouldn't be tempted, I just wanted to assert a corrections of my own about how NULL works in SQL:

    NULL = NULL evaluates to UNKNOWN.

    UNKNOWN is a logical value.

    NULL is a data value.

    This is easy to prove e.g.

    SELECT NULL = NULL

    correctly generates an error in SQL Server. If the result was a data value then we would expect to see NULL, as some answers here (wrongly) suggest we would.

    The logical value UNKNOWN is treated differently in SQL DML and SQL DDL respectively.

    In SQL DML, UNKNOWN causes rows to be removed from the resultset.

    For example:

    CREATE TABLE MyTable
    (
     key_col INTEGER NOT NULL UNIQUE, 
     data_col INTEGER
     CHECK (data_col = 55)
    );
    
    INSERT INTO MyTable (key_col, data_col)
       VALUES (1, NULL);
    

    The INSERT succeeds for this row, even though the CHECK condition resolves to NULL = NULL. This is due defined in the SQL-92 ("ANSI") Standard:

    11.6 table constraint definition

    3)

    If the table constraint is a check constraint definition, then let SC be the search condition immediately contained in the check constraint definition and let T be the table name included in the corresponding table constraint descriptor; the table constraint is not satisfied if and only if

    EXISTS ( SELECT * FROM T WHERE NOT ( SC ) )

    is true.

    Read that again carefully, following the logic.

    In plain English, our new row above is given the 'benefit of the doubt' about being UNKNOWN and allowed to pass.

    In SQL DML, the rule for the WHERE clause is much easier to follow:

    The search condition is applied to each row of T. The result of the where clause is a table of those rows of T for which the result of the search condition is true.

    In plain English, rows that evaluate to UNKNOWN are removed from the resultset.

提交回复
热议问题