【问题标题】:In SQL Server, what does "SET ANSI_NULLS ON" mean?在 SQL Server 中,“SET ANSI_NULLS ON”是什么意思?
【发布时间】:2012-04-03 17:37:45
【问题描述】:

定义说:

当 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_NULLs 只关注这样的查询(其中WHERE 包含特定词NULL)?

SELECT Region
FROM employees
WHERE Region = NULL

【问题讨论】:

  • 在您复制第 1 段的官方文档的第 4 段中,答案是否已经存在,即:->“SET ANSI_NULLS ON 仅在比较是 NULL 变量或文字 NULL。如果比较的两边都是列或复合表达式,则设置不会影响比较。"

标签: sql tsql stored-procedures


【解决方案1】:

这意味着如果@regionNULL,则在您的第一个示例中使用时不会返回任何行,即使表中有RegionNULL 的行。

ANSI_NULLS 处于打开状态时(无论如何您都应该始终设置为打开状态,因为将来会删除不打开它的选项),任何(至少)操作数之一为@ 的比较操作987654329@ 产生第三个逻辑值 - UNKNOWN(相对于 TRUEFALSE)。

UNKNOWN 值通过任何组合布尔运算符传播,如果它们尚未确定(例如 ANDFALSE 操作数或 ORTRUE 操作数)或否定(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,则NULLNULL 相比的结果为TRUE

NULL 与非NULL 值进行比较总是得到FALSE2

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


*多年后终于发现了这段文字的神秘含义。它的实际意思是,对于这些比较,设置没有任何效果,它总是像设置为 ON。如果它声明 SET ANSI_NULLS OFF 是无效的设置会更清楚。

【讨论】:

  • 所以如果我理解正确的话:它也会影响“Where Region = @region”短语的结果,而不仅仅是当我专门写“Where Region=null”时?
  • 不会是 (t1.Val1 = t2.Val1 还是 (t1.Val1 为空而 t2.Val1 为空)) ???
  • @Gregbert - 鉴于 and 具有更高的优先级,我不确定您认为额外的一对括号会添加什么。
  • @Damien_The_Unbeliever 只是为了那些不知情的人的可读性。
  • “不启用它的选项将在未来被删除” - 请问您有这方面的参考吗?
【解决方案2】:

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

ANSI_NULLS 只会在 @Region 的值为 null 时产生影响,即当您的第一个查询实质上变成第二个查询时。

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

【讨论】:

    【解决方案3】:

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

            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
    

    【讨论】:

      【解决方案4】:

      https://docs.microsoft.com/en-us/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 !
      

      【讨论】:

        【解决方案5】:

        设置 ANSI_NULLS 为开

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

        设置 ANSI_NULLS 关闭

        当列包含空值时结束

        【讨论】:

        • 这个答案对已经陈述的答案有什么额外的作用?警惕为旧问题添加新答案 - 它们应该包含对已发布解决方案的扩展解释,或提供新见解 - From Review
        【解决方案6】:

        如果 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 开启

        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 关闭

        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)
        

        【讨论】:

        • +1 是唯一明确区分 WHERE X IS NULLWHERE X = NULL 以及 ANSI_NULLS 如何影响结果的答案。尽管有过分热心的反对投票者的尝试,但这应该是公认的答案!
        • +1 用于解释使用示例,它总是更清晰,更简洁,而不是冗长的句子。
        【解决方案7】:

        我想这里主要是:

        从不用户:

        • @anything = NULL
        • @anything &lt;&gt; NULL
        • @anything != null

        始终使用:

        • @anything IS NULL
        • @anything IS NOT NULL

        【讨论】:

          猜你喜欢
          • 2019-07-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-27
          • 1970-01-01
          • 1970-01-01
          • 2018-10-06
          相关资源
          最近更新 更多