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

定义说:

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

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

SELECT EmployeeID, LastName, FirstName, Region FROM employees WHERE Region=@region 

或者ANSI_NULL只关心像这样的查询( WHERE包含特定的单词null )?

 SELECT EmployeeID, LastName, FirstName, Region FROM employees WHERE Region=null 

这意味着如果在第一个示例中使用@regionNULL情况下,即使表中的RegionNULL ,也不会返回任何行。

ANSI_NULLS是打开的时候(无论如何你总是应该设置这个选项,因为没有打开它的选项将来会被删除),那么至less有一个操作数为NULL比较操作会产生第三个逻辑值- UNKNOWN (而不是TRUEFALSE )。

UNKNOWN值尚未确定(例如ANDFALSE操作数或ORTRUE操作数)或否定( NOT ),则通过任何组合布尔运算符传播UNKNOWN值。

WHERE子句用于过滤由FROM子句产生的结果集,使得WHERE子句的总体值必须为TRUE以防止行被过滤掉。 因此,如果通过比较产生UNKNOWN ,将导致该行被过滤掉。


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

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

来自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 。 而关于这个操作数的文档没有什么可说的:

当您比较两个NULLexpression式时,结果取决于ANSI_NULLS设置:

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

如果ANSI_NULLS设置为OFF ,则NULLNULL的结果为TRUE

NULL与非NULL值进行比较总是会导致FALSE 2

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


*这段文字的神秘含义终于在几年后被发现。 它实际上意味着,对于那些比较,设置没有效果, 它总是作为设置为ON 。 如果它声明SET ANSI_NULLS OFF是没有任何影响的设置,它会更清晰。

SET QUOTED_IDENTIFIER开启/closures

它指定SQL Server如何处理单引号和双引号中定义的数据。

当它被设置为ON时 ,在双引号 “”中定义的任何字符集被视为T-SQL标识符 (表名称,过程名称,列名… .etc)

当在单引号“'中定义的任何字符集被视为文字时。

 SET QUOTED_IDENTIFIER ON CREATE TABLE "SELECT" ("TABLE" int) -- SUCCESS GO SET QUOTED_IDENTIFIER ON SELECT "sometext" AS Value -- FAIL because “sometext” is not a literal 

当它被设置为OFF时 ,单引号或双引号中定义的字符集将被视为文字

 SET QUOTED_IDENTIFIER OFF CREATE TABLE "SELECT"(“TABLE” int) -- FAIL GO SET QUOTED_IDENTIFIER OFF SELECT "sometext" AS Value -- SUCCESS as “sometext” is treated litral --The default behavior is ON in any database. 

SET ANSI_NULLS ON / OFF:

ANSI_NULLS选项指定SQL Server如何使用NULL值处理比较操作。

当它被设置为ON时使用=和<>NULL进行任何比较都将产生错误的值 。 这是ISO定义的标准行为。 所以要用NULL值进行比较,我们需要使用IS NULL和IS NOT NULL。

当它被设置为OFF时,任何使用=和<>的比较都将像往常一样工作,即NULL = NULL返回true,1 = NULL返回false。

 SET ANSI_NULLS ON IF NULL = NULL PRINT 'same' ELSE PRINT 'different' --result: different SET ANSI_NULLS ON IF NULL IS NULL PRINT 'same' ELSE PRINT 'different' -- result: same --============================== SET ANSI_NULLS OFF IF NULL = NULL PRINT 'same' ELSE PRINT 'different' --result: same (now NULL = NULL works as 1=1) --The default behavior is ON in any database. 

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

ANSI_NULLS只会在@Region值为null ,即当第一个查询基本上成为第二个查询时。

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

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

https://docs.microsoft.com/en-us/sql/t-sql/statements/set-ansi-nulls-transact-sql

当SET ANSI_NULLS为ON时,即使列名中有空值,使用WHERE column_name = NULL的SELECT语句也会返回零行。 即使列名中有非空值,使用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 ! 

SET ANSI_NULLS ON

IT返回表中包含空值的所有值

SET ANSI_NULLSclosures

它在列包含空值时结束