Как работает ANSI_NULLS в TSQL?
SET ANSI_NULLS OFF
кажется, дает разные результаты в TSQL в зависимости от того, сравниваете ли вы поле из таблицы или значение. Может ли кто-нибудь помочь мне понять, почему последние 2 моих запроса не дают результатов? Я не ищу решение, просто объяснение.
select 1 as 'Col' into #a
select NULL as 'Col' into #b
--This query gives results, as expected.
SET ANSI_NULLS OFF
select * from #b
where NULL = Col
--This query gives results, as expected.
SET ANSI_NULLS OFF
select * from #a
where NULL != Col
--This workaround gives results, too.
select * from #a a, #b b
where isnull(a.Col, '') != isnull(b.Col, '')
--This query gives no results, why?
SET ANSI_NULLS OFF
select * from #a a, #b b
where a.Col != b.Col
--This query gives no results, why?
SET ANSI_NULLS OFF
select * from #a a, #b b
where b.Col != a.Col
2 ответа
Причина, по которой последние два запроса терпят неудачу, заключается в том, что SET ANSI_NULLS ON/OFF
применяется только при сравнении с переменной или значением NULL. Он не применяется при сравнении значений столбцов. С БОЛ:
SET ANSI_NULLS ON влияет на сравнение, только если один из операндов сравнения является либо переменной, равной NULL, либо литералом NULL. Если обе стороны сравнения являются столбцами или составными выражениями, настройка не влияет на сравнение.
Что-нибудь по сравнению с нулевым значением терпит неудачу. Даже сравнение двух нулевых значений не удастся. Даже!= Потерпит неудачу из-за (IMHO) глупой обработки NULL.
Тем не менее, запросы!= Можно переписать так:
select * from #a a where a.Col not in (select b.Col from #b b)
Последний запрос идентичен второму или последнему запросу, так как порядок сравнения не имеет значения.
Кстати, ваш обходной путь работает просто потому, что вы проверяете нулевое значение в столбце #b.Col и явно конвертируете его в "", что затем позволяет вашему запросу выполнить сравнение строк между ними. Альтернативный способ написания, который будет:
select * from #a a, #b b
where a.Col != COALESCE(b.Col, '')