В SQL-сервере, если у вас есть nullParam=NULL
предложение where, оно всегда оценивается как false. Это нелогично и вызвало у меня много ошибок. Я понимаю, IS NULL
и IS NOT NULL
ключевые слова являются правильным способом сделать это. Но почему SQL-сервер ведет себя так?
sql
sql-server
null
Байрон Уитлок
источник
источник
Ответы:
В этом случае думайте о нуле как о «неизвестном» (или «не существует»). В любом из этих случаев вы не можете сказать, что они равны, потому что вы не знаете ценность любого из них. Итак, null = null оценивается как не true (false или null, в зависимости от вашей системы), потому что вы не знаете значений, чтобы сказать, что они равны. Это поведение определено в стандарте ANSI SQL-92.
РЕДАКТИРОВАТЬ: Это зависит от вашей настройки ansi_nulls . если вы отключили ANSI_NULLS, это БУДЕТ иметь значение true. Запустите следующий код для примера ...
источник
(NaN == NaN) == false && (NaN != Nan) == false && (NaN < NaN) == false && ...
- потому что, ну, если это не число, вы просто не можете много говорить об этом; это что-то неизвестное. Эта концепция является разумной, даже если она не понятна людям, которые никогда ее не видели.NULL
выражение SQL может рассматриваться как отдельная математическая переменная. Таким образом, выражениеNULL = NULL
должно рассматриваться какx = y
, гдеx
иy
являются несвязанными переменными. Теперь, если кто-то спросит вас, какова ценностьx = y
? Единственный разумный ответ - «некоторыеz
». Таким образом , у нас есть(x = y) = z
- или, транскрибировать его обратно в SQL,(NULL = NULL) = NULL
.Сколько лет Фрэнку? Я не знаю (ноль)
Сколько лет Ширли? Я не знаю (ноль)
Фрэнк и Ширли одного возраста?
Правильный ответ должен быть «я не знаю» (ноль), а не «нет», так как Фрэнк и Ширли могут быть одного возраста, мы просто не знаем.
источник
null = null
уступаетFALSE
, а неNULL
.Здесь я надеюсь уточнить мою позицию.
Это
NULL = NULL
оцениватьFALSE
неправильно. Хакер и Мистер правильно ответилиNULL
. Вот почему. Дуэйн Кристенсен написал мне в комментарии Скотту Айви :Они могут быть разными или равными, вы не знаете, пока не откроете оба подарка. Кто знает? Вы пригласили двух людей, которые не знают друг друга и оба сделали вам один и тот же подарок - редкий, но не невозможный § .
Таким образом, вопрос: эти два НЕИЗВЕСТНЫХ представляют одинаково (равно, =)? Правильный ответ: НЕИЗВЕСТНО (то есть
NULL
).Этот пример был призван продемонстрировать, что «.. (
false
илиnull
, в зависимости от вашей системы) ..» является правильным ответом - это не так, толькоNULL
правильно в 3VL (или вы можете принять систему, которая дает неправильные ответы? )Правильный ответ на этот вопрос должен подчеркнуть следующие два момента:
Поэтому я повторяю: SQL не имеет смысла заставлять интерпретировать рефлексивное свойство равенства, которое утверждает, что:
.. в 3VL (
TRUE
,FALSE
,NULL
). Ожидание людей будет соответствовать 2VL (TRUE
,FALSE
, что даже в SQL справедливо для всех других значений), то естьx = x
всегда вычислятьсяTRUE
для любого возможного значения х - без исключений.Также обратите внимание, что значения NULL являются допустимыми « ненулевыми значениями » (как утверждают их апологеты), которые можно назначать как значения атрибутов (??) как часть переменных отношения. Таким образом, они являются приемлемыми значениями каждого типа (домена), а не только типа логических выражений.
И это была моя точка зрения :
NULL
как ценность, это «странный зверь». Без эвфемизма я предпочитаю говорить: ерунда .Я думаю, что эта формулировка намного более ясна и менее спорна - извините за мое плохое знание английского языка.
Это только одна из проблем NULL. Лучше избегать их полностью, когда это возможно.
§ мы обеспокоены ценностями здесь, поэтому тот факт, что два подарка всегда являются двумя разными физическими объектами, не является обоснованным возражением; если вы не уверены, извините, это не то место, чтобы объяснить разницу между значением и семантикой «объекта» (реляционная алгебра имеет семантику значения с самого начала - см. информационный принцип Кодда; я думаю, что некоторые разработчики СУБД SQL не даже не заботится об общей семантике).
§§ насколько мне известно, это аксиома, принятая (в той или иной форме, но всегда интерпретируемая в 2VL) с древности и именно потому , что она настолько интуитивна. 3VLs (в действительности это семейство логик) - это гораздо более свежая разработка (но я не уверен, когда она была впервые разработана).
Примечание: если кто-то представит типы Bottom , Unit и Option как попытки оправдать значения NULL в SQL, я буду убежден только после довольно подробного изучения, которое покажет, как реализации SQL с NULL имеют систему звукового типа, и, в конце концов, прояснит, что такое NULL (эти «значения-не-совсем-значения»).
В дальнейшем я процитирую некоторых авторов. Любая ошибка или упущение, вероятно, принадлежит мне, а не авторам оригинала.
Джо Селко о SQL NULL
Я вижу, Джо Селко часто цитируется на этом форуме. Видимо, он очень уважаемый автор здесь. Итак, я сказал себе: «что он пишет о SQL NULL? Как он объясняет NULL многочисленные проблемы?». У одного из моих друзей есть электронная версия SQL Джо Селко для умных людей: продвинутый SQL-программирование, 3-е издание . Посмотрим.
Во-первых, оглавление. Больше всего меня поражает количество упоминаний NULL в самых разных контекстах:
и так далее. Это звучит как "неприятный особый случай" для меня.
Я расскажу о некоторых из этих случаев с выдержками из этой книги, пытаясь ограничиться основным, из соображений авторского права. Я думаю, что эти цитаты подпадают под доктрину «добросовестного использования», и они могут даже стимулировать покупку книги - так что я надеюсь, что никто не будет жаловаться (в противном случае мне придется удалить большую часть, если не все). Кроме того, по той же причине я не буду сообщать фрагменты кода. Извини за это. Купите книгу, чтобы прочитать о данных рассуждениях.
Номера страниц между круглыми скобками в дальнейшем.
Опять эта ерунда "ценность, но не совсем ценность". Остальное мне кажется вполне разумным.
По поводу SQL, NULL и бесконечности:
Реализации SQL не определились с тем, что на самом деле означает NULL в определенных контекстах:
Джо Селко цитирует Дэвида Макговерана и СиДжея Дейта:
NULL как наркомания :
Мое единственное возражение здесь состоит в том, чтобы «использовать их правильно», что плохо взаимодействует с определенным поведением реализации.
(разделитель)
Но UNKNOWN сам по себе является источником проблем, поэтому CJ Date в своей книге, цитируемой ниже, рекомендуется в главе 4.5. Как избежать пустых значений в SQL :
Прочитайте «ВНУТРИ» на НЕИЗВЕСТНОМ, также связанном ниже.
(разделитель)
Возражение: NULL сбивает с толку даже людей, которые хорошо знают SQL, см. Ниже.
(разделитель)
(разделитель)
(разделитель)
(разделитель)
(разделитель)
(разделитель)
Обсуждение GROUP BY:
Это означает, что для предложения GROUP BY NULL = NULL не оценивается как NULL, как в 3VL, но оценивается как TRUE.
Стандарт SQL сбивает с толку:
И так далее. Я думаю, что достаточно Celko.
Дата CJ на пустых значениях SQL
CJ Date более радикально относится к NULL: избегайте NULL в SQL, точка. Фактически, глава 4 его теории SQL и реляционной теории: как писать точный код SQL называется «NO DUPLICATES, NO NULLS», с подразделами «4.4. Что не так с NULL?» и «4.5 Избегание пустых значений в SQL» (перейдите по ссылке: благодаря Google Книгам вы можете читать некоторые страницы в режиме онлайн).
Фабиан Паскаль о SQL NULL
Из практических вопросов по управлению базами данных - справочник для практикующего мышления (нет выдержек в Интернете, извините):
источник
NULL
это не ценность.(NULL = NULL) -> FALSE
. Чтобы процитировать документацию дляANSI_NULLS
: «Когда указано ON, все сравнения с нулевым значением оцениваются как UNKNOWN . Если задано OFF, сравнение не-UNICODE значений с нулевым значением оценивается как TRUE, если оба значения равны NULL.»Может быть, это зависит, но я подумал, что
NULL=NULL
оцениваетNULL
большинство операций с NULL в качестве операнда.источник
То, что вы не знаете, что такое две вещи, не означает, что они равны. Если, когда вы думаете о себе,
NULL
вы думаете о «NULL» (строка), то вам, вероятно, нужен другой тест на равенство, такой как Postgresql'sIS DISTINCT FROM
ANDIS NOT DISTINCT FROM
Из документации PostgreSQL на «Функции сравнения и операторы»
источник
Понятие NULL сомнительно, если не сказать больше. Кодд представил реляционную модель и концепцию NULL в контексте (и продолжил предлагать более одного вида NULL!) Однако, реляционная теория эволюционировала со времени оригинальных работ Кодда: некоторые из его предложений были с тех пор отброшены (например, первичный ключ) и другие никогда не завоевывали популярность (например, тета-операторы). В современной теории отношений (истинно теории отношений, я должен подчеркнуть), NULL просто не существует. Смотрите Третий Манифест. http://www.thethirdmanifesto.com/
Язык SQL сталкивается с проблемой обратной совместимости. NULL нашел свой путь в SQL, и мы застряли с ним. Возможно, реализация
NULL
в SQL имеет недостатки (реализация SQL Server делает вещи еще более сложными из-за егоANSI_NULLS
опции).Я рекомендую избегать использования пустых столбцов в базовых таблицах.
Хотя, возможно, я не должен поддаваться искушению, я просто хотел заявить о своих собственных исправлениях о том, как
NULL
работает SQL:NULL
=NULL
оценивает доUNKNOWN
.UNKNOWN
это логическое значение.NULL
это значение данных.Это легко доказать, например
SELECT NULL = NULL
правильно генерирует ошибку в SQL Server. Если бы результат был значением данных, то мы ожидали бы увидеть
NULL
, как некоторые ответы здесь (ошибочно) предполагают, что мы это сделаем.Логическое значение
UNKNOWN
обрабатывается по-разному в SQL DML и SQL DDL соответственно.В SQL DML
UNKNOWN
вызывает удаление строк из набора результатов.Например:
INSERT
Преуспевает для этой строки, даже еслиCHECK
условие решаетNULL = NULL
. Это обусловлено стандартом SQL-92 («ANSI»):Прочитайте это снова внимательно, следуя логике.
На простом английском языке нашей новой строке выше дана «польза от сомнений» в том, что ты есть,
UNKNOWN
и ей позволено пройти.В SQL DML правило для
WHERE
предложения гораздо проще следовать:На простом английском языке строки, которые оцениваются
UNKNOWN
как, удаляются из набора результатов.источник
В technet есть хорошее объяснение того, как работают нулевые значения.
Нуль означает неизвестность.
Следовательно, логическое выражение
значение = NULL
не оценивается как ложное, оно оценивается как нулевое, но если это конечный результат предложения where, то ничего не возвращается. Это практичный способ сделать это, так как возвращать нуль было бы трудно для зачатия.
Интересно и очень важно понять следующее:
Если в запросе мы имеем
и
затем
"value = @ param" оценивается как нулевое
"@param is null" оценивается как истинное
"id = @ anotherParam" оценивается как истинное
Таким образом, выражение для оценки становится
(ноль или правда) и правда
Мы могли бы подумать, что здесь «null Or true» будет оцениваться как null, и, таким образом, все выражение станет нулевым, и строка не будет возвращена.
Это не так. Зачем?
Поскольку значение «null Or true» оценивается как true, что очень логично, поскольку если один операнд является истинным с оператором Or, то независимо от значения другого операнда операция вернет true. Таким образом, не имеет значения, что другой операнд неизвестен (ноль).
Таким образом, мы наконец имеем true = true и, таким образом, строка будет возвращена.
Примечание: с той же кристально чистой логикой, что "null Or true" оценивается как true, "null And true" оценивается как null.
Обновление:
Хорошо, просто чтобы завершить, я хочу добавить сюда и остальное, что довольно забавно по отношению к вышесказанному.
«ноль или ложь» оценивается как ноль, «ноль и ложь» оценивается как ложь. :)
Логика, конечно, все еще очевидна, как и раньше.
источник
Потому что
NULL
означает «неизвестное значение» и два неизвестных значения не могут быть равны.Итак, если по нашей логике
NULL
N ° 1 равноNULL
N ° 2, то мы должны это как-то сказать:где известное значение
-1
N ° 1 равно-1
N ° 2источник
nullParam1 = -1
иnullParam2 =NULL
и авиакатастрофа .... должно бытьISNULL(NULLIF(@nullParam1, @nullParam2), NULLIF(@nullParam2, nullParam1)) IS NULL
Все ответы здесь, кажется, приходят с точки зрения CS, поэтому я хочу добавить один с точки зрения разработчика.
Для разработчика NULL очень полезен. Ответы здесь говорят, что NULL означает неизвестный, и, возможно, в теории CS это правда, не помню, это было давно. В реальной разработке, хотя, по моему опыту, это происходит примерно в 1% случаев. Остальные 99% используются в тех случаях, когда значение не UNKNOWN, но оно известно, чтобы быть отсутствующим.
Например:
Client.LastPurchase
, для нового клиента. Не известно, известно, что он еще не совершил покупку.При использовании ORM с отображением « Таблица на иерархию классов» некоторые значения просто не отображаются для определенных классов.
При отображении древовидной структуры корень обычно
Parent = NULL
И многое другое ...
Я уверен, что большинство разработчиков в какой-то момент написали
WHERE value = NULL
, не получили никаких результатов, и именно так они узнали оIS NULL
синтаксисе. Посмотрите, сколько голосов имеют этот вопрос и связанные с ним.Базы данных SQL являются инструментом, и они должны быть спроектированы так, чтобы их пользователям было проще понять.
источник
NULL не равен ничему, даже самому себе. Мое личное решение для понимания поведения NULL - избегать его максимально возможного использования :).
источник
Вопрос:
одно неизвестное равно другому неизвестному?
(NULL = NULL) На
этот вопрос никто не может ответить, поэтому по умолчанию он имеет значение true или false, в зависимости от настроек ansi_nulls.
Однако вопрос:
эта неизвестная переменная неизвестна?
Этот вопрос совершенно другой, и на него можно ответить правдиво.
nullVariable = null сравнивает значения
nullVariable is null сравнивает состояние переменной
источник
Путаница возникает из-за уровня косвенности (абстракции), возникающего при использовании NULL .
Возвращаясь к аналогии «что под елкой», «Неизвестно» описывает состояние знаний о том, что находится во вставке А.
Поэтому, если вы не знаете, что находится во вставке А, вы говорите, что это «Неизвестно», но это не значит, что «Неизвестно» находится внутри коробки . В коробке есть что-то, кроме неизвестного, возможно, какой-то объект, или, возможно, ничего нет в коробке.
Точно так же, если вы не знаете, что находится во вставке B, вы можете пометить свой уровень знаний о содержимом как «Неизвестный».
Так вот кикер: Ваше состояние знаний о Box А равно вашему уровню знаний о Графе . (Уровень ваших знаний в обоих случаях - «Неизвестно» или «Я не знаю, что находится в коробке».) Но содержимое коробок может совпадать или не совпадать.
Возвращаясь к SQL, в идеале вы сможете сравнивать значения только тогда, когда знаете, что это такое. К сожалению, метка, описывающая недостаток знаний, хранится в самой ячейке , поэтому мы склонны использовать ее в качестве значения. Но мы не должны использовать это как значение, потому что это привело бы к тому, что «содержимое блока A равно содержимому блока B, когда мы не знаем, что находится в блоке A, и / или мы не знаем, что находится в блоке B. (Логично, что «если я не знаю, что находится в блоке А, и если я не знаю, что находится в блоке В, то, что находится в блоке А = то, что находится в блоке В», неверно.)
Yay, Dead Horse.
источник
У MSDN есть хорошая описательная статья о нулях и логике трех состояний, которую они порождают.
Вкратце, спецификация SQL92 определяет NULL как неизвестный, а NULL, используемый в следующих операторах, приводит к непредвиденным результатам для непосвященных:
источник
null неизвестен в sql, поэтому мы не можем ожидать, что два неизвестных будут одинаковыми.
Однако вы можете получить такое поведение, установив для ANSI_NULLS значение Выкл. (По умолчанию включено). Вы можете использовать оператор = для нулей.
источник
null
, научитесь понимать его или просто измените таблицу, чтобы иметь типы int, и обновите столбцы.Вы работаете на правительство, регистрируя информацию о гражданах. Это включает в себя национальный идентификатор для каждого человека в стране. Около 40 лет назад у дверей церкви остался ребенок, никто не знает, кто их родители. Этого человека отец удостоверение личности
NULL
. Два таких человека существуют. Подсчитайте людей, которые имеют одинаковый идентификатор отца, по крайней мере, с одним другим человеком (людьми, которые являются братьями и сестрами). Ты тоже считаешь этих двоих?Ответ - нет, вы не знаете, потому что мы не знаем, являются ли они братьями и сестрами или нет.
Предположим, у вас нет
NULL
опции, и вместо этого вы используете какое-то заранее определенное значение для представления «неизвестного», возможно, пустой строки или цифры 0 или символа * и т. Д. Тогда в ваших запросах будет иметь значение * = * , 0 = 0, и «» = «» и т. Д. Это не то, что вы хотите (в соответствии с примером выше), и как вы часто можете забыть об этих случаях (пример выше - это очевидный случай вне обычного повседневного мышления). ), тогда вам нужен язык, чтобы помнить для вас, чтоNULL = NULL
это не так.Голь на выдумки хитра.
источник
Просто дополнение к другим замечательным ответам:
источник
Если вы ищете выражение, возвращающее true для двух NULL, вы можете использовать:
Это полезно, если вы хотите скопировать данные из одной таблицы в другую.
источник
Например, тест на равенство в операторе case, когда предложение может быть изменен с
в
Если я хочу обработать пробелы и пустую строку как равные NULL, я часто также использую тест на равенство:
источник