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 поводиться так.

Відповіді:


13

Це дивовижна поведінка, але зі сторінки MSDN SET ANSI_NULLSми можемо принаймні знати, що таке очікувана поведінка. Ще одна причина ніколи не використовувати ANSI_NULLS OFF:

SET ANSI_NULLSвпливає на порівняння, лише якщо один з операндів порівняння є або змінною, яка є, NULLабо літералом NULL. Якщо обидві сторони порівняння є стовпцями або складовими виразами, настройка не впливає на порівняння.


8

Незважаючи на те, що з документації на msdn це не може бути кришталево ясним, я вважаю, що ви знайдете таке дійсне

"SET ANSI_NULLS ON впливає на порівняння, лише якщо один із операндів порівняння є або змінною, яка є NULL, або буквальною NULL. Якщо обидві сторони порівняння є стовпцями або складовими виразами, налаштування не впливає на порівняння."

Дивіться це /programming/2866714/how-does-ansi-nulls-work-in-tsql


Дякую Скотту та ypercube, обидві ваші відповіді є суттєвими для такої поведінки, тому я підтримую обидві ваші відповіді.
цзяо

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) поводилися по-різному, більше схожі на те, що ви хочете.

Однак якщо ви шукаєте проблему на переповнення стека та обміну стеками, ви знайдете багато довгих ниток, які обговорюють проблеми.


3
Я колись читав пов'язаний пост від Роберта Шелдона, але в ньому (ІМХО) немає жодної теорії чи доказів, які б пояснювали поведінку мого прикладу.
jyao

1
"Немає двох NULL значень." Гаразд, але навіть люди, які знають, що очікували б навпаки, коли ансі нулі відкладеться. Тим більше, що WHERE NULL = NULLприбутковість відповідає дійсності.
ypercubeᵀᴹ

1

Щоб додати до дискусії, визначення стандарту SQL92 NULL можна інтерпретувати неоднозначно. Ось хороший підсумок обробки NULL та інтерпретації з різних СУБД з люб’язності sqlite.org.

ВІДКРИТТЯ : Я начебто пам'ятаю, як читав про "неоднозначність" SQL92 зі старої версії (як, наприклад, 6-8 років тому) сторінки sqlite.org, зв'язаної вище, але ця сторінка оновлюється з тих пір.

Відповідь RLF, наведена вище, має добру цитату, але якщо я не згоден з Робертом Шелдоном, це лише тому, що я вважаю, що "щось не існує" (тобто NULL ) філософськи, а англомовна семантично рівнозначна "щось інше, що не існує ". Якщо я хочу зрозуміти логіку Шелдона, тоді можна було б визначити визначення NULL також NULL. (Якщо його не існує, то як ми можемо це визначити? Моторошно, так?)

Я бачу варіацію заварювання Парадокса Рассела ( і головний біль). : - \

Але знову ж таки, це дискусія з семантики англійської мови ( NOT SQL), і тут йдеться про дискусію з філософії . :-)


PS Я новачок у цій спільноті SE; якщо це обговорювалося ad nauseum раніше, я вибачаюся.
pr1268

1
Де саме в стандарті неоднозначність?
ypercubeᵀᴹ

@ ypercubeᵀᴹ: Я вважаю, що неоднозначність полягає в спробі "вписати" 3VL в булеву форму. Приєднання таблиці до порівнянь NULL можна інтерпретувати декількома різними способами.
pr1268

Я погодився б про непослідовність, але не про неоднозначність.
ypercubeᵀᴹ

1
@ ypercubeᵀᴹ: Досить справедливо ... Я цитував лише те, що сказала старша версія сторінки sqlite.org, яку я зв'язав вище ("SQL92 неоднозначний щодо обробки та інтерпретації NULL" чи чогось подібного). Але я не хочу сперечатися. Можливо, сама сторінка sqlite.org була оманливою та / або зовсім невірною. Що ймовірно пояснює, чому воно було оновлено.
pr1268
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.