Сравнение значений NULL в таблице

13

Я всегда озадачен некоторым загадочным поведением t-sql, например:

-- Create table t and insert values.  
use tempdb
CREATE TABLE dbo.t (a INT NULL);  
-- insert 3 values
INSERT INTO dbo.t values (NULL),(0),(1);  
GO  
set ansi_nulls off -- purposely turn off, so we can allow NULL comparison, such as null = null
go
-- expect 3 rows returned but only 2 returned (without null value row)
select * from dbo.t where a = a 

Речь идет не о том, как извлечь все строки в таблице, а также о том, как избежать использования ANSI_NULLS.

Я просто хочу выяснить, почему t-sql ведет себя так.

jyao
источник

Ответы:

13

Это удивительное поведение, но со страницы MSDN SET ANSI_NULLSмы, по крайней мере, можем знать, что это ожидаемое поведение. Еще одна причина никогда не использовать ANSI_NULLS OFF:

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

ypercubeᵀᴹ
источник
8

Хотя это может быть не совсем ясно из документации MSDN, я думаю, вы найдете следующее

«SET ANSI_NULLS ON влияет на сравнение, только если один из операндов сравнения является либо переменной, равной NULL, либо литералом NULL. Если обе стороны сравнения являются столбцами или составными выражениями, настройка не влияет на сравнение».

Смотрите этот /programming/2866714/how-does-ansi-nulls-work-in-tsql

Скотт Ходжин
источник
Спасибо Скотту и ypercube, оба ваших ответа относятся к пунктам этого поведения, поэтому я одобряю оба ваших ответа.
Цзяо
Иперкуб был первым :)
Скотт Ходжин
4

Роберт Шелдон в следующем посте от 2015 года обсуждает NULL-поведение и почему они иногда (но не всегда) терпят неудачу

https://www.simple-talk.com/sql/t-sql-programming/how-to-get-nulls-horribly-wrong-in-sql-server/

Он описывает 13 ошибок NULL, которые программист может легко отключить.

Ошибка № 1: не зная, что означает NULL

Объяснение: NULL - это не значение, несуществующее значение. Это не ноль. Это не пустая строка. Значение не может быть равно NULL. Нет двух значений NULL равных .

Это основная проблема, но обязательно прочитайте о других ошибках.

Да, более ранние версии (я полагаю, до SQL Server 7) вели себя по-другому, больше как то, что вы хотите.

Однако, если вы будете искать проблему в Stack Overflow и Stack Exchange, вы обнаружите много длинных потоков, обсуждающих проблемы.

ДКП
источник
3
Однажды я прочитал связанный пост от Роберта Шелдона, но у него нет (ИМХО) какой-либо теории или доказательств, объясняющих поведение моего примера.
Цзяо
1
«Нет двух значений NULL, равных.» Хорошо, но даже люди, которые знают это, ожидают обратного, когда ANSI NULL отключен. Тем более, что WHERE NULL = NULLдает значение true, когда параметр имеет значение.
ypercubeᵀᴹ
1

Чтобы добавить к обсуждению, определение NULL в стандарте SQL92 можно интерпретировать неоднозначно. Вот хорошее резюме обработки и интерпретации NULL из различных СУБД, предоставленных sqlite.org.

РАСКРЫТИЕ ИНФОРМАЦИИ : Я помню, что читал о «неоднозначности» SQL92 из более старой версии (например, 6-8 лет назад) страницы sqlite.org, указанной выше, но с тех пор эта страница была обновлена.

Ответ RLF выше имеет хорошую цитату, но если я не согласен с Робертом Шелдоном, то это только потому, что я считаю, что «что-то, что не существует» (то есть NULL ), философски и семантически эквивалентно английскому языку «что - то еще, что не существует». ». Если я хочу понять логику Шелдона, то можно было бы объявить определение NULL также NULL. (Если его не существует, то как мы можем его определить? Жутко, да?)

Я вижу вариацию назревающего парадокса Рассела ( и головную боль). : - \

Но опять же, это обсуждение семантики английского языка ( НЕ SQL), и философские дебаты здесь . :-)

pr1268
источник
PS Я новичок в этом сообществе SE; если это обсуждалось до тошноты , то прошу прощения.
pr1268
1
Где именно эта двусмысленность в стандарте?
ypercubeᵀᴹ
@ ypercubeᵀᴹ: я считаю, что двусмысленность заключается в попытке «вписать» 3VL в логическое значение. Соединения таблиц с NULL-сравнениями можно интерпретировать несколькими различными способами.
pr1268
Я бы согласился с несогласованностью, но не с неоднозначностью.
ypercubeᵀᴹ
1
@ ypercubeᵀᴹ: Достаточно справедливо ... Я только цитировал то, что говорила старая версия страницы sqlite.org, на которую я ссылался выше («SQL92 неоднозначен в отношении обработки и интерпретации NULL» или что-то очень похожее). Но я не хочу спорить. Возможно, страница sqlite.org сама по себе вводит в заблуждение и / или полностью неверна. Что, вероятно, объясняет, почему оно было обновлено.
pr1268