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


91

定义说:

当SET ANSI_NULLS为ON时,即使column_name中有空值,使用WHERE column_name = NULL的SELECT语句也将返回零行。即使column_name中包含非空值,使用WHERE column_name <> NULL的SELECT语句也将返回零行。

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

SELECT Region
FROM employees
WHERE Region = @region

还是ANSI_NULL只关心类似这样的查询(其中WHERE包括特定单词NULL)?

SELECT Region
FROM employees
WHERE Region = NULL

1
在复制第一段的官方文档的第四段中是否还没有答案,即:->“ SET ANSI_NULLS ON仅在比较的一个操作数是NULL变量的情况下才会影响比较或文字NULL。如果比较的两面都是列或复合表达式,则该设置不会影响比较。”
user1451111 '18

Answers:


67

这意味着在第一个示例中使用@regionisNULL时,即使表中Regionis所在的行也不会返回if的行NULL

ANSI_NULLSon时(无论如何,您都应该始终设置为on,因为将来将不启用它的选项将被删除),(至少)操作数之一为的任何比较操作都会NULL产生第三个逻辑值- UNKNOWN(相对于TRUEFALSE)。

UNKNOWN如果尚未确定(例如AND,使用FALSE操作数或OR使用TRUE操作数)或取反(NOT),则值会通过任何组合的布尔运算符传播。

WHERE子句用于过滤该子句产生的结果集,以使该FROM子句的总值WHERE必须是TRUE不被滤除的行。因此,如果UNKNOWN通过任何比较产生an ,则将导致该行被过滤掉。


@ user1227804的答案包含以下引用:

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

来自*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。并且文档=中没有关于操作数的任何内容:

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

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

如果ANSI_NULLS设置为OFF,结果NULLNULLTRUE

NULLNULL值进行比较总是得出FALSE2

但是,12都不正确-两次比较的结果均为UNKNOWN


*多年后终于发现了本文的神秘含义。实际上,对于这些比较而言,该设置没有任何作用,并且始终像该设置为ON一样起作用。如果它说那SET ANSI_NULLS OFF是没有影响的设置,本来会更清楚。


1
因此,如果我没看错:它也会影响“ Where Region = @region”这句话的结果,而不仅是在我专门编写“ Where Region = null”时?
Rodniko'3

6

如果@Region不是null值(请说@Region = 'South'),则无论ANSI_NULLS的值如何,都不会返回Region字段为null的行。

ANSI_NULLS仅在@Regionis的值(null即您的第一个查询实质上成为第二个查询)时有所不同。

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


5

如果将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')

设置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)

设置ANSI_NULLS OFF

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)

2
+1是唯一的答案,可以清楚地区分WHERE X IS NULL和和WHERE X = NULL,以及ANSI_NULLS如何影响结果。尽管有过分热心的失败者尝试,但这应该是公认的答案!
Riegardt Steyn

1
+1来解释使用示例,这将总是更清晰,更简洁,而不是冗长的句子。
peter.aryanto

3

设置ANSI_NULLS ON

IT返回表中的所有值,包括空值

关闭ANSI_NULLS

当列包含空值时结束


2
这个答案对已经说明的答案又增加了什么?警惕在旧问题上添加新答案-它们​​应包含已发布解决方案的扩展解释,或提供新见解-评论来自
Takarii,2008年

1

我想这里的主要是:

永不使用者:

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

始终使用:

  • @anything IS NULL
  • @anything IS NOT NULL

0

设置ANSI NULLS OFF将使NULL = NULL比较返回true。EG:

        SET ANSI_NULLS OFF
        select * from sys.tables
        where principal_id = Null

将返回如下所示的结果:zcwInvoiceDeliveryType 744547 NULL zcExpenseRptStatusTrack 2099048 NULL ZCVendorPermissions 2840564 NULL ZCWOrgLevelClientFee 4322525 NULL

虽然此查询不会返回任何结果:

        SET ANSI_NULLS ON 
        select * from sys.tables
        where principal_id = Null

0

https://docs.microsoft.com/zh-cn/sql/t-sql/statements/set-ansi-nulls-transact-sql

当SET ANSI_NULLS为ON时,即使column_name中有空值,使用WHERE column_name = NULL的SELECT语句也将返回零行。即使column_name中包含非空值,使用WHERE column_name <> NULL的SELECT语句也将返回零行。

例如

DECLARE @TempVariable VARCHAR(10)
SET @TempVariable = NULL

SET ANSI_NULLS ON
SELECT 'NO ROWS IF SET ANSI_NULLS ON' where    @TempVariable = NULL
-- IF ANSI_NULLS ON , RETURNS ZERO ROWS


SET ANSI_NULLS OFF
SELECT 'THERE WILL BE A ROW IF ANSI_NULLS OFF' where    @TempVariable =NULL
-- IF ANSI_NULLS OFF , THERE WILL BE ROW !
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.