It means that no rows will be returned if @region
is NULL
, when used in your first example, even if there are rows in the table where Region
is NULL
.
When ANSI_NULLS
is on (which you should always set on anyway, since the option to not have it on is going to be removed in the future), any comparison operation where (at least) one of the operands is NULL
produces the third logic value - UNKNOWN
(as opposed to TRUE
and FALSE
).
UNKNOWN
values propagate through any combining boolean operators if they're not already decided (e.g. AND
with a FALSE
operand or OR
with a TRUE
operand) or negations (NOT
).
The WHERE
clause is used to filter the result set produced by the FROM
clause, such that the overall value of the WHERE
clause must be TRUE
for the row to not be filtered out. So, if an UNKNOWN
is produced by any comparison, it will cause the row to be filtered out.
@user1227804's answer includes this quote:
If both sides of the comparison are columns or compound expressions, the setting does not affect the comparison.
from SET ANSI_NULLS
*
However, I'm not sure what point it's trying to make, since if two NULL
columns are compared (e.g. in a JOIN
), the comparison still fails:
create table #T1 (
ID int not null,
Val1 varchar(10) null
)
insert into #T1(ID,Val1) select 1,null
create table #T2 (
ID int not null,
Val1 varchar(10) null
)
insert into #T2(ID,Val1) select 1,null
select * from #T1 t1 inner join #T2 t2 on t1.ID = t2.ID and t1.Val1 = t2.Val1
The above query returns 0 rows, whereas:
SELECT * FROM #T1 t1 INNER JOIN #T2 t2
ON t1.ID = t2.ID
AND ( t1.Val1 = t2.Val1
OR t1.Val1 IS NULL
AND t2.Val1 IS NULL )
Returns one row. So even when both operands are columns, NULL
does not equal NULL
. And the documentation for =
doesn't have anything to say about the operands:
When you compare two NULL
expressions, the result depends on the ANSI_NULLS
setting:
If ANSI_NULLS
is set to ON
, the result is NULL
1, following the ANSI convention that a NULL
(or unknown) value is not equal to another NULL
or unknown value.
If ANSI_NULLS
is set to OFF
, the result of NULL
compared to NULL
is TRUE
.
Comparing NULL
to a non-NULL
value always results in FALSE
2.
However, both 1 and 2 are incorrect - the result of both comparisons is UNKNOWN
.
*The cryptic meaning of this text was finally discovered years later. What it actually means is that, for those comparisons, the setting has no effect and it always acts as if the setting were ON. Would have been clearer if it had stated that SET ANSI_NULLS OFF
was the setting that had no effect.