views:

77

answers:

3

This is a problem one of our developers brought to me. He stumbled across an old stored procedure which used 'WHERE col = NULL' several times. When the stored procedure is executed it returns data.

If the query inside the stored procedure is executed manually it will not return data unless the 'WHERE col = NULL' references are changed to 'WHERE col IS NULL'.

Can anyone explain this behavior?

+5  A: 

That's by design: if you compare anything to null, it evaluates to unknown. Any logic with unknown is itself unknown. So any statement with anything = null will always be false.

The important difference is between these two constructs:

1 = null --> unknown
1 is null --> false

So:

1 = null or 1=1 --> unknown (false)
1 is null or 1=1 --> true

So as you can see, unknown taints an entire expression.

Based on the comments, a better answer would probably be checking for ANSI_NULLs, with:

SELECT SESSIONPROPERTY ('ANSI_NULLS')

If this returns false, the = null construct would work like is null:

set ansi_nulls on -- default
SELECT SESSIONPROPERTY ('ANSI_NULLS') -- 1
select 1 where not null = 1 -- no rows returned
set ansi_nulls off
SELECT SESSIONPROPERTY ('ANSI_NULLS') -- 0
select 1 where not null = 1 -- returns a row

The default is ansi_nulls on though, and it's very unusual to see it turned off. A stored procedure does remember the setting from the time it was created:

set ansi_nulls off
go
create procedure dbo.TestNulls as select 1 where not null = 1
go
set ansi_nulls on
exec dbo.TestNulls -- Still prints a row

You can check the saved settings by scripting the procedure from SSMS.

Andomar
If u downvote, plz provide a reason. Specially if u downvote a *correct* answer...
Remus Rusanu
@Remus, both of the answers so far are correct FOR SOME OTHER QUESTION. They both missed that the OP said that the stored procedure was giving data, they only had the problem when they ran the query manually. I'd really like to see the correct answer to this question. I've boldened the important point in the question.
Lance Roberts
Isn't this answer backwards?
RBarryYoung
I think the point is that the query is running correctly even with the incorrect syntax.
James Westgate
The OP clearly understands how NULLs work. What he doesn't understand is why Col = NULL is returning data when it shouldn't.
Larry Lustig
@Lance Roberts: I think a comment would get your point across better than an unexplained downvote?
Andomar
So could his SP be running with ANSI_NULLS off, but his manual session running with it on?
Lance Roberts
+1 since it looks like your edit was the answer. Thanks for updating it.
Lance Roberts
+1, never knew about SESSIONPROPERTY ()
KM
A: 

In SQL, X = NULL will always evaluate to false, since NULL represents the absence of data, one cannot tell whether it is equal to "another" absence of data or not (NULL = NULL is false). This is why the IS keyword exists...

Romain
+1. Why did someone -1 it? This is a correct answer.
Etamar L.
@Etamar, no read the question, and the comment I left on Andomar's answer.
Lance Roberts
I understand proper NULL handling. That is not my question.
Kenneth
Probably because it fails to answer the question, which is why `X = NULL` fails to evaluate to false in the context of the stored procedure.
eswald
+3  A: 

OK, guess I should have made this an answer:

Check the ANSI_NULLS setting

RBarryYoung