在SQL Server中,"SET ANSI_NULLS ON"是什么意思?

Rod*_*iko 80 sql t-sql stored-procedures

定义说:

当SET ANSI_NULLS为ON时,即使column_name中存在空值,使用WHERE column_name = NULL的SELECT语句也会返回零行.使用WHERE column_name <> NULL的SELECT语句返回零行,即使column_name中存在非空值也是如此.

这是否意味着此查询中不包含空值?

SELECT Region
FROM employees
WHERE Region = @region
Run Code Online (Sandbox Code Playgroud)

或者ANSI_NULL只关注像这样的查询(其中WHERE包含特定的单词NULL)?

SELECT Region
FROM employees
WHERE Region = NULL
Run Code Online (Sandbox Code Playgroud)

Dam*_*ver 60

这意味着,没有行被返回,如果@regionNULL,即使有在表中的行中的第一个例子中使用时,RegionNULL.

ANSI_NULLS打开时(无论如何你应该始终设置,因为将来不会删除没有打开的选项),任何比较操作,其中(至少)其中一个操作数NULL产生第三个逻辑值 - UNKNOWN(而不是TRUEFALSE).

UNKNOWN值传播通过任何结合的布尔运算符,如果他们不已经决定(例如,AND具有FALSE操作数或ORTRUE操作数)或否定(NOT).

WHERE子句用于过滤FROM子句生成的结果集,这样子句的整体值WHERE必须是TRUE不过滤掉的行.因此,如果UNKNOWN通过任何比较生成a,则会导致该行被过滤掉.


@ user1227804的答案包含这个引用:

如果比较的两侧都是列或复合表达式,则该设置不会影响比较.

来自*SET ANSI_NULLS

但是,我不确定它要做什么,因为如果NULL比较两列(例如a 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
Run Code Online (Sandbox Code Playgroud)

上面的查询返回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)
Run Code Online (Sandbox Code Playgroud)

返回一行.所以即使两个操作数都是列,NULL也不相等NULL.并且文档对=操作数没有任何说明:

比较两个NULL表达式时,结果取决于ANSI_NULLS设置:

如果ANSI_NULLS设置为ON,则结果为NULL1,遵循ANSI约定,NULL(或未知)值不等于另一个NULL或未知值.

如果ANSI_NULLS设置为OFF,则NULL比较结果NULLTRUE.

NULLNULL值相比总是导致FALSE2.

但是,12都不正确 - 两个比较的结果都是UNKNOWN.


*多年后终于发现了这篇文章的神秘含义.它实际意味着,对于那些比较,设置没有任何效果,它总是表现为设置为ON.如果说它SET ANSI_NULLS OFF是没有影响的设置,那就更清楚了.


小智 27

如果 ANSI_NULLS 设置为“ON”,并且如果我们在编写 select 语句时对 NULL 列值应用 = , <> ,则它将不会返回任何结果。

例子

create table #tempTable (sn int, ename varchar(50))

insert into #tempTable
values (1, 'Manoj'), (2, 'Pankaj'), (3, NULL), (4, 'Lokesh'), (5, 'Gopal')
Run Code Online (Sandbox Code Playgroud)

设置 ANSI_NULLS ON

select * from #tempTable where ename is NULL -- (1 row(s) affected)
select * from #tempTable where ename = NULL -- (0 row(s) affected)
select * from #tempTable where ename is not NULL -- (4 row(s) affected)
select * from #tempTable where ename <> NULL -- (0 row(s) affected)
Run Code Online (Sandbox Code Playgroud)

设置 ANSI_NULLS 关闭

select * from #tempTable where ename is NULL -- (1 row(s) affected)
select * from #tempTable where ename = NULL -- (1 row(s) affected)
select * from #tempTable where ename is not NULL -- (4 row(s) affected)
select * from #tempTable where ename <> NULL -- (4 row(s) affected)
Run Code Online (Sandbox Code Playgroud)

  • +1 是唯一清楚区分“WHERE X IS NULL”和“WHERE X = NULL”以及 ANSI_NULLS 如何影响结果的答案。尽管有过度热心的反对者的尝试,但这应该是公认的答案! (4认同)
  • +1使用示例进行解释,这总是比冗长的句子更清晰、更简洁。 (4认同)

use*_*142 9

我想这里最主要的是:

切勿使用:

  • @anything = NULL
  • @anything <> NULL
  • @anything != null

因为 ANSI NULL ON/OFF 可能会改变你的逻辑。

始终使用:

  • @anything IS NULL
  • @anything IS NOT NULL

因为无论 ANSI NULL 是什么,它都会工作


SWe*_*eko 5

如果@Region不是null值(假设@Region = 'South')它将不返回Region字段为null的行,而不管ANSI_NULLS的值.

ANSI_NULLS只会在@Regionis 的值时产生差异null,即当您的第一个查询基本上成为第二个查询时.

在这种情况下,ANSI_NULLS ON将不返回任何行(因为null = null将产生未知的布尔值(aka null))并且ANSI_NULLS OFF将返回Region字段为null的任何行(因为null = null将产生true)