SQL Server 2008R2: SET ANSI_NULLS OFF 不影响与空值的合并匹配

SQL Server 2008R2: SET ANSI_NULLS OFF does not affect merge matching with null values

我已经阅读了 "SET ANSI_NULLS OFF" 在当前会话中的使用,以便能够将 NULL = NULL 评估为真,例如以下示例显示了 ANSI_NULLS ON 和 ANSI_NULLS OFF 之间的差异:

查询 A:

SET ANSI_NULLS OFF

IF(NULL = NULL)
    SELECT 'NULL = NULL'
ELSE 
    SELECT 'NO MATCH'

结果:'NULL = NULL'

查询 B:

SET ANSI_NULLS ON

IF(NULL = NULL)
    SELECT 'NULL = NULL'
ELSE 
    SELECT 'NO MATCH'

结果:'NO MATCH'

所以这显示了 ON 和 OFF 设​​置之间的区别。

在标准 select 语句的 where 子句中使用它时,这似乎也有效。

但是,当源字段和目标字段为空时,这在合并中似乎不起作用。

重现一个简单的场景:

创建测试TABLE:

CREATE TABLE [dbo].[TestTable]
(
    [Id] [INT] IDENTITY(1,1) NOT NULL,
    [SomeText] [NVARCHAR](100) NULL,
    [Counter] [INT] NOT NULL,

    CONSTRAINT [PK_TestTable] 
        PRIMARY KEY CLUSTERED ([Id] ASC)
) ON [PRIMARY]
GO

合并查询

MERGE INTO TestTable AS Target
USING (VALUES(NULL)) AS Source(SomeText) ON Target.SomeText = Source.SomeText

WHEN MATCHED THEN
    UPDATE SET Target.Counter = Target.Counter + 1

WHEN NOT MATCHED THEN
    INSERT (SomeText) VALUES(Source.SomeText);

如果匹配,则计数器加1。如果不匹配,则插入新行。当 运行 查询两次时,结果是两行,这不是我在 ansi_nulls 关闭时所期望的结果。

如果我将值 NULL 更改为 'test',则匹配工作正常,例如

使用(值(NULL))=>使用(值('test'))

使用合并时是否有一些特殊行为可以解释这一点?还是 sql 服务器中的错误?

注意:我不是在寻找使用 ISNULL(...) 解决方案或类似解决方案的变通方法。这样我无法确保有效使用匹配字段的索引。最初的问题是关于与多个匹配字段的合并,其中多个匹配字段可能恰好为空。

仅解决方法!

如果您想处理空值,您可以将 ON 条件从 Target.SomeText = Source.SomeText 更改为 IS NOT DISTINCT FROM 等价物:

MERGE INTO TestTable AS Target
USING (VALUES(NULL)) AS Source(SomeText)
ON EXISTS (SELECT Target.SomeText INTERSECT SELECT Source.SomeText)
WHEN MATCHED THEN
UPDATE SET Target.Counter = ISNULL(Target.Counter,1) + 1
WHEN NOT MATCHED THEN
INSERT (SomeText) VALUES(Source.SomeText);

db<>fiddle demo

我同意您应该避免使用 SET ANSI_NULLS OFF 的评论,因为它已被弃用。

SET ANSI_NULLS 仅在非常有限的情况下影响 NULL 比较的语义。具体来说

affects a comparison only if one of the operands of the comparison is either a variable that is NULL or a literal NULL. If both sides of the comparison are columns or compound expressions, the setting does not affect the comparison. (source)

当您将文字 NULL 包装在派生 table 中时,不再满足此条件,因此预计此设置不会如您所愿。