Чому НЕ входить із набором, що містить NULL, завжди повертає FALSE / NULL?


21

У мене був запит (для Postgres та Informix) із NOT INпропозицією, що містить підзапит, який у деяких випадках повертає NULLзначення, внаслідок чого цей пункт (і весь запит) нічого не повертають.

Який найкращий спосіб зрозуміти це? Я вважав це NULLяк щось, що не має значення, і тому не очікував, що запит не вдасться, але, очевидно, це не правильний спосіб думати NULL.

Відповіді:


29

Булева логіка - або Три логічна логіка

  • IN - це скорочення для серії умов АБО
  • x NOT IN (1, 2, NULL) те саме, що NOT (x = 1 OR x = 2 OR x = NULL)
  • ... те саме, що x <> 1 AND x <> 2 AND x <> NULL
  • ... те саме, що true AND true AND unknown**
  • ... = unknown**
  • ... що майже те саме, що і falseв цьому випадку, оскільки не перейде WHEREумова **

Тепер, ось чому народне використання EXISTS+, NOT EXISTSа не IN+ NOT IN. Також див . Використання логіки NOT стосовно індексів для отримання додаткової інформації

** Примітка: unknownте саме, що falseв кінці виразу в WHEREумові.
Поки вираз оцінюється, то невідомо, чому
див. Коментар @ kgrittn нижче


10
Навіть з уточненням, це технічно неправильно і таким чином, що може когось спалити. Наприклад, якщо ви вважаєте, що x <> NULLце вирішує питання FALSE, ви можете розраховувати NOT (x <> NULL)на оцінку TRUE, а це не так. Обидва оцінюють UNKNOWN. Хитрість полягає в тому, що рядок вибирається лише в тому випадку, якщо в WHEREпункті (якщо він присутній) оцінюється значення TRUE- рядок опущено, якщо цей пункт оцінює FALSEабо UNKNOWN. Така поведінка (загалом і зокрема NOT INприсудок) відповідає стандарту SQL.
kgrittn

Також NULL NOT IN (some_subquery)не слід повертати зовнішній рядок, за винятком випадків, якщо some_subqueryне повертає жодних рядків. Ось чому план виконання, коли обидва стовпці є Null-здатним, може бути значно дорожчим. Приклад SQL Server
Мартін Сміт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.