SQL Server 2008R2: SET ANSI_NULLS OFF не влияет на сопоставление слиянием с нулевыми значениями - PullRequest
0 голосов
/ 21 декабря 2018

Я прочитал об использовании "SET ANSI_NULLS OFF" для текущего сеанса, чтобы иметь возможность оценить NULL = NULL в true, например, в следующем примере показано различие между ANSI_NULLS ON и ANSI_NULLS OFF:

QUERY A:

SET ANSI_NULLS OFF

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

РЕЗУЛЬТАТ: 'NULL = NULL'

QUERY B:

SET ANSI_NULLS ON

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

РЕЗУЛЬТАТ: «НЕТ МАТЧ»

Таким образом, это показывает разницу между настройками ВКЛ и ВЫКЛ.

Кажется, это также работает при использовании его в предложении where в стандартном операторе select.

ОДНАКО, похоже, что это не работает при слиянии, когда поля источника и цели равны нулю.

Воспроизведение простого сценария:

CREATETEST 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 QUERY

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', совпадение будет работать нормально, например,

USING (VALUES (NULL)) => USING (VALUES ('test')) *

Существует ли какое-то особое поведение при использовании слияний, которое объясняет это?Или это ошибка в сервере sql?

ПРИМЕЧАНИЕ: я не ищу обходного пути, использующего ISNULL (...) - решение или что-то подобное.Таким образом, я не могу обеспечить эффективное использование индекса соответствующих полей.Первоначальная проблема касается слияния с несколькими полями совпадения, где несколько из них могут быть нулевыми.

Ответы [ 2 ]

0 голосов
/ 24 декабря 2018

SET ANSI_NULLS влияет только на семантику NULL сравнений в очень ограниченных случаях.В частности, это

влияет на сравнение, только если один из операндов сравнения является либо переменной, равной NULL, либо литералом NULL.Если обе стороны сравнения являются столбцами или составными выражениями, настройка не влияет на сравнение.( source )

Когда вы переносите литерал NULL в производную таблицу, это условие больше не выполняется, поэтому не ожидается, что этот параметр будет работать так, как вы хотите.

0 голосов
/ 21 декабря 2018

Только обходной путь!

Если вы хотите обработать пустые значения, вы можете изменить условие 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, поскольку оно устарело.

...