这意味着如果@region 是NULL,则在您的第一个示例中使用时不会返回任何行,即使表中有Region 是NULL 的行。
当ANSI_NULLS 处于打开状态时(无论如何您都应该始终设置为打开状态,因为将来会删除不打开它的选项),任何(至少)操作数之一为@ 的比较操作987654329@ 产生第三个逻辑值 - UNKNOWN(相对于 TRUE 和 FALSE)。
UNKNOWN 值通过任何组合布尔运算符传播,如果它们尚未确定(例如 AND 与 FALSE 操作数或 OR 与 TRUE 操作数)或否定(NOT)。
WHERE 子句用于过滤FROM 子句产生的结果集,使得WHERE 子句的整体值必须为TRUE 才能不被过滤掉。因此,如果通过任何比较产生UNKNOWN,则会导致该行被过滤掉。
@user1227804 的answer 包含此引用:
如果比较的两边都是列或复合表达式,则设置不影响比较。
来自SET ANSI_NULLS*
但是,我不确定它试图说明什么,因为如果比较两个 NULL 列(例如在 JOIN 中),比较仍然失败:
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
上述查询返回 0 行,而:
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 )
返回一行。因此,即使两个操作数都是列,NULL 也不等于 NULL。而documentation for = 对操作数没有什么要说的:
比较两个NULL 表达式时,结果取决于ANSI_NULLS 设置:
如果ANSI_NULLS 设置为ON,则结果为NULL1,遵循NULL(或未知)值不等于另一个@987654358 的ANSI 约定@ 或未知值。
如果将ANSI_NULLS 设置为OFF,则NULL 与NULL 相比的结果为TRUE。
将NULL 与非NULL 值进行比较总是得到FALSE2。
但是,1 和 2 都不正确 - 两个比较的结果都是 UNKNOWN。
*多年后终于发现了这段文字的神秘含义。它的实际意思是,对于这些比较,设置没有任何效果,它总是像设置为 ON。如果它声明 SET ANSI_NULLS OFF 是无效的设置会更清楚。