Чи може хтось пояснити наступну поведінку в SQL?
SELECT * FROM MyTable WHERE MyColumn != NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn <> NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn IS NOT NULL (568 Results)
Чи може хтось пояснити наступну поведінку в SQL?
SELECT * FROM MyTable WHERE MyColumn != NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn <> NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn IS NOT NULL (568 Results)
Відповіді:
<>
є стандартним SQL-92; !=
є його еквівалентом. Обидва оцінюють за значеннями, а NULL
це не так - NULL
це заповнювач, який стверджує, що немає значення.
Ось чому ви можете використовувати IS NULL
/ IS NOT NULL
як предикати для таких ситуацій.
Така поведінка не характерна для SQL Server. Всі відповідні стандартам діалекти SQL працюють однаково.
Примітка . Для порівняння, якщо ваше значення не є нульовим , ви використовуєте IS NOT NULL
, тоді як для порівняння з ненульовим значенням використовуєте <> 'YOUR_VALUE'
. Я не можу сказати, чи моє значення дорівнює чи ні NULL, але я можу сказати, чи є моє значення NULL чи NOT NULL. Я можу порівняти, якщо моя вартість щось інше, ніж NULL.
!=
до ~ 9i, як я розумію, що принесло багато синтаксису ANSI-92. Я вважаю, що MySQL схожий, починаючи підтримку в 4.x.
!=
могла бути включена в більш пізню специфікацію як альтернатива <>
. Не маю на руках нових специфікацій, тому я не можу сказати точно.
WHERE MyColumn != NULL
чи WHERE MyColumn = NULL
детермінований? Або іншими словами, чи гарантовано завжди повертати 0 рядків, незалежно від того, MyColumn
є нульовим в базі даних чи ні?
!=
лише оцінює значення, виконуючи щось на зразок WHERE MyColumn != 'somevalue'
, не повертаються записи NULL.
NULL не має значення, і тому його не можна порівняти за допомогою операторів скалярного значення.
Іншими словами, жодне значення ніколи не може бути рівним (або не дорівнює) NULL, оскільки NULL не має значення.
Отже, SQL має спеціальний IS NULL і НЕ NULL предикатів для роботи з NULL.
'a' != null
НЕ повертає значення ( true
/ 1
) протилежно інтуїтивному і час від часу виловлює мене! Я б подумав, що "якесь значення порівняно з жодним значенням" завжди буде "не рівним", але, можливо, це тільки я?!?
SELECT * FROM MyTable WHERE coalesce(MyColumn, 'x') <> 'x'
призначити константу, якщо це значення NULL, якщо ви надаєте відповідний тип даних для вартового значення x (у цьому випадку рядок / діаграма). Це синтаксис TSQL, але Oracle та інші двигуни мають схожі функції.
Зауважте, що така поведінка є типовою (ANSI) поведінкою.
Якщо ти:
SET ANSI_NULLS OFF
http://msdn.microsoft.com/en-us/library/ms188048.aspx
Ви отримаєте різні результати.
SET ANSI_NULLS OFF
мабуть, піде в майбутньому ...
create unique index UK_MyTable on MyTable (Column) where Column is not null
): msdn.microsoft.com/en-us/library/cc280372.aspx
SET ANSI_NULLS
значення ВИМКНЕНО, оператори порівняння рівні (=) і не рівні (<>) не відповідають стандарту ISO. Оператор SELECT, який використовує, WHERE column_name = NULL
повертає рядки, які мають нульові значення у колонці_імена. WHERE column_name <> NULL
Оператор SELECT, який використовує, повертає рядки, у яких стовпці не мають значення. Крім того, оператор SELECT, який використовує WHERE column_name <> XYZ_value
повертає всі рядки, які не є XYZ_value, і які не є NULL. ІМХО, це останнє твердження здається трохи дивним, оскільки це виключення нулів з результатів!
У SQL все, що ви оцінюєте / обчислюєте за NULL
результатами, НЕВІДОМЛЕНО
Ось чому SELECT * FROM MyTable WHERE MyColumn != NULL
або SELECT * FROM MyTable WHERE MyColumn <> NULL
дає 0 результатів.
Для перевірки NULL
значень передбачена функція isNull.
Більше того, ви можете використовувати IS
оператора, як ви використовували в третьому запиті.
Сподіваюсь, це допомагає.
Єдиний тест на NULL - це NULL або NE NULL. Тестування на рівність є безглуздим, оскільки за визначенням ніхто не знає, що таке значення.
Ось стаття з Вікіпедії для читання:
Ми використовуємо
SELECT * FROM MyTable WHERE ISNULL(MyColumn, ' ') = ' ';
щоб повернути всі рядки, де MyColumn - NULL, або всі рядки, де MyColumn - порожній рядок. Для багатьох "кінцевих споживачів" проблема NULL проти порожнього рядка - це відмінність без потреби та точки плутанини.
Я просто не бачу, що функціональна і безперебійна причина, коли нулі не можна порівняти з іншими значеннями або іншими нулями, тому що ми можемо чітко порівняти їх і сказати, що вони однакові чи ні в нашому контексті. Смішно. Просто через деякі логічні висновки та послідовність нам потрібно постійно турбуватися з цим. Це не функціонально, зробіть його більш функціональним і залиште це філософам та вченим, щоб вони зробили висновок, послідовний він чи ні, і чи дотримується він "загальної логіки". :) Хтось може сказати, що це через індекси чи щось інше, я сумніваюся, що ці речі не могли бути зроблені для підтримки нулів, таких як значення. Це те саме, що порівнювати два порожні келихи, один - келих для лози, а другий - пиво, ми не порівнюємо типи предметів, але значення, які вони містять, те саме, що можна порівняти з int та varchar, з нульовим. ' s що ще простіше, це нічого, і те, що мають дві спільності нічого, вони однакові, явно порівнянні мною і всіма іншими, хто пише sql, тому що ми постійно порушуємо цю логіку, порівнюючи їх дивними способами через деякі стандарти ANSI. Чому б не використати комп’ютерну потужність, щоб зробити це для нас, і я сумніваюся, що це сповільнить ситуацію, якщо все, що пов'язане, будуватиметься з цим на увазі. "Це не нуль, це нічого", це не яблуко, це apfel, давай ... Функціонально це твій друг, і тут теж є логіка. Зрештою, важливим є лише функціональність, а використання нулів таким чином приносить більшу чи меншу функціональність та простоту використання. Це корисніше? тому що ми постійно порушуємо цю логіку, порівнюючи їх дивними способами через деякі стандарти ANSI. Чому б не використати комп’ютерну потужність, щоб зробити це для нас, і я сумніваюся, що це сповільнить ситуацію, якщо все, що пов'язане, будуватиметься з цим на увазі. "Це не нуль, це нічого", це не яблуко, це apfel, давай ... Функціонально це твій друг, і тут теж є логіка. Зрештою, важливим є лише функціональність, а використання нулів таким чином приносить більшу чи меншу функціональність та простоту використання. Це корисніше? тому що ми постійно порушуємо цю логіку, порівнюючи їх дивними способами через деякі стандарти ANSI. Чому б не використати комп’ютерну потужність, щоб зробити це для нас, і я сумніваюся, що це сповільнить ситуацію, якщо все, що пов'язане, будуватиметься з цим на увазі. "Це не нуль, це нічого", це не яблуко, це apfel, давай ... Функціонально це твій друг, і тут теж є логіка. Зрештою, важливим є лише функціональність, а використання нулів таким чином приносить більшу чи меншу функціональність та простоту використання. Це корисніше? s не яблуко це apfel, давай ... Функціонально є твоїм другом, і тут теж є логіка. Зрештою, важливим є лише функціональність, а використання нулів таким чином приносить більшу чи меншу функціональність та простоту використання. Це корисніше? s не яблуко це apfel, давай ... Функціонально є твоїм другом, і тут теж є логіка. Зрештою, важливим є лише функціональність, а використання нулів таким чином приносить більшу чи меншу функціональність та простоту використання. Це корисніше?
Розглянемо цей код:
SELECT CASE WHEN NOT (1 = null or (1 is null and null is null)) THEN 1 ELSE 0 end
Хто з вас знає, що поверне цей код? З або без НЕ він повертає 0. Для мене це не функціонально і заплутано. У c # це все як належить, операції порівняння повертають значення, логічно, це теж дає значення, тому що якщо воно не було, то для порівняння немає нічого (крім нічого :)). Вони просто "сказали": все, порівняно з нульовим, "повертає" 0, і це створює багато обхідних ситуацій та головних болів.
Це код, який привів мене сюди:
where a != b OR (a is null and b IS not null) OR (a IS not null and b IS null)
Мені просто потрібно порівняти, якщо два поля (там, де) мають різні значення, я міг би використовувати функцію, але ...
NULL Не можна порівняти жодне значення за допомогою операторів порівняння. NULL = NULL помилково. Нуль не є цінністю. Оператор IS спеціально розроблений для обробки порівнянь NULL.
null = null
де можна скористатися 1=0
в якомусь спеціальному запиті. І якщо вони скаржаться, я зміню це на null != null
:)
Старе питання, але наступне може запропонувати ще кілька деталей.
null
не представляє значення або невідоме значення. Він не вказує, чому немає значення, що може призвести до певної неоднозначності.
Припустимо, ви запускаєте такий запит:
SELECT *
FROM orders
WHERE delivered=ordered;
тобто ви шукаєте рядки, де ordered
і delivered
дати однакові.
Що можна очікувати, коли один чи обидва стовпці є недійсними?
Оскільки принаймні одна дата невідома, не можна сподіватися сказати, що дві дати однакові. Це також той випадок, коли обидві дати невідомі: як вони можуть бути однаковими, якщо ми навіть не знаємо, що вони?
З цієї причини будь-який вираз, що трактується null
як значення, повинен бути невдалим. У цьому випадку вона не збігатиметься. Це також має місце, якщо ви спробуєте наступне:
SELECT *
FROM orders
WHERE delivered<>ordered;
Знову ж таки, як можна сказати, що дві величини не є однаковими, якщо ми не знаємо, що вони є.
SQL має специфічний тест на відсутні значення:
IS NULL
Зокрема, вона не порівнює значення, а скоріше шукає пропущені значення.
Нарешті, що стосується !=
оператора, наскільки я знаю, він насправді не є жодним із стандартів, але він дуже широко підтримується. Це було додано, щоб програмісти з деяких мов відчували себе як вдома. Відверто кажучи, якщо програмісту важко запам'ятати, якою мовою вони користуються, вони починають погано починати.
NULL
ми маємо на увазі, що ми порівнюємо значення з "мати NULL
значення", а не значення з "невизначеним значенням, яке NULL
має нижнє підкладка" , але що ми не знаємо ", що, очевидно, ми не збираємося ніколи знати. Це дійсно полегшило б справи.
IS NULL
набагато складніше, ніж писати = NULL
. Я думаю, що було б більш послідовно, якби це WHERE columnA = columnB
було те саме тлумачення WHERE columnA = NULL
, а не трактувати останню як особливий випадок. Пам'ятайте, що NULL
це не цінність. У мовах програмування , де він є законним , щоб перевірити variable == null
це , тому що null
має інше значення; це не являє собою щось невідоме, а навмисне скидання значення. Не так із SQL.
IS NULL
AND =NULL
. Але погляньте на останній Ховер. Я втомився відчувати це знову і знову, змушуючи робити зайві навантаження? додаткова перевірка ...
Я хотів би запропонувати цей код, який я зробив, щоб дізнатися, чи є зміна значення,
i
є новим значенням і d
є старим (хоча порядок не має значення). З цього приводу перехід від значення до нуля або навпаки - це зміна, але від нуля до нуля не є (звичайно, зі значення на інше значення - це зміна, але від значення до того ж не є).
CREATE FUNCTION [dbo].[ufn_equal_with_nulls]
(
@i sql_variant,
@d sql_variant
)
RETURNS bit
AS
BEGIN
DECLARE @in bit = 0, @dn bit = 0
if @i is null set @in = 1
if @d is null set @dn = 1
if @in <> @dn
return 0
if @in = 1 and @dn = 1
return 1
if @in = 0 and @dn = 0 and @i = @d
return 1
return 0
END
Використовувати цю функцію ви можете
declare @tmp table (a int, b int)
insert into @tmp values
(1,1),
(1,2),
(1,null),
(null,1),
(null,null)
---- in select ----
select *, [dbo].[ufn_equal_with_nulls](a,b) as [=] from @tmp
---- where equal ----
select *,'equal' as [Predicate] from @tmp where [dbo].[ufn_equal_with_nulls](a,b) = 1
---- where not equal ----
select *,'not equal' as [Predicate] from @tmp where [dbo].[ufn_equal_with_nulls](a,b) = 0
Результати:
---- in select ----
a b =
1 1 1
1 2 0
1 NULL 0
NULL 1 0
NULL NULL 1
---- where equal ----
1 1 equal
NULL NULL equal
---- where not equal ----
1 2 not equal
1 NULL not equal
NULL 1 not equal
Використання sql_variant робить його сумісним для різних типів
NULL - це не що-небудь ... невідомо. NULL нічого не дорівнює. Ось чому ви повинні використовувати магічну фразу IS NULL замість = NULL у своїх SQL запитах
Ви можете посилатися на це: http://weblogs.sqlteam.com/markc/archive/2009/06/08/60929.aspx
<>
в 92 специфікаціях, але більшість постачальників підтримує!=
та / або він включається в більш пізню специфікацію, як 99 або 03.