Consider the following Transact sql.
DECLARE @table TABLE(val VARCHAR(255) NULL)
INSERT INTO @table (val) VALUES('a')
INSERT INTO @table (val) VALUES('b')
INSERT INTO @table (val) VALUES('c')
INSERT INTO @table (val) VALUES('d')
INSERT INTO @table (val) VALUES(NULL)
select val
from @table
where val not in ('a')
I would expect this to return
b, c, d, NULL
but instead it returns
b, c, d
Why is this the case? Is NULL not evaluated? Is NULL somehow in the set ‘a’?
The Answer
By default, NULL, to SQL, means “unknown”. So, any comparison to “unknown” is “unknown”.
For example, if a stranger is standing next to Bob, and you want to ask the question, “Is the stranger’s name the same as Bob’s?”. The answer is unknown.
Since you’re asking, “Return any records where the value is not ‘A'”. When it gets to that NULL column, SQL still says, “I don’t know”. Since the expression doesn’t evaluate to true, that record isn’t returned.
The Solution
Any expression that compares NULL to a constant will always be NULL, so use the special
IS NULLandIS NOT NULLto test for NULL values.This will get you
b,c,d, andNULL:The Workaround
You can change the default behavior for NULLs: