Подтвердить что ты не робот

Почему SQL не поддерживает "= null" вместо "null"?

Я не спрашиваю , если. Я знаю, что это не так.

Мне любопытно, почему. Я прочитал документы поддержки, такие как о работе с нулями в MySQL, но на самом деле они не дают никаких оснований. Они только повторяют мантру, которую вы должны использовать вместо "null".

Это всегда беспокоило меня. Когда вы выполняете динамический SQL (те редкие времена, когда это нужно сделать), было бы намного проще передать "null" в where where так:

@where = "where GroupId = null"

Это будет простая замена обычной переменной. Вместо этого мы должны использовать if/else блоки для создания таких вещей, как:

if @groupId is null then
     @where = "where GroupId is null"
else
     @where = "where GroupId = @groupId"
end

В более сложных задачах, это огромная боль в шее. Существует ли конкретная причина, по которой SQL и все основные производители RDBMS этого не допускают? Какой-то конфликт ключевых слов или конфликт значений, которые он создал?

Edit:

Проблема с множеством ответов (на мой взгляд) заключается в том, что каждый настраивает эквивалентность между нулем и "я не знаю, что это за значение". Там огромная разница между этими двумя вещами. Если null означает "там значение, но неизвестно", я бы 100% согласился с тем, что nulls не могут быть равными. Но SQL null не означает этого. Это означает, что существует значение нет. Любые два результата SQL, которые являются нулевыми, не имеют значения. Нет значение не равно неизвестно. Две разные вещи. Это важное различие.

Изменить 2:

Другая проблема, которую я имею, заключается в том, что другие HLL разрешают null = null совершенно нормально и разрешают ее соответствующим образом. В С#, например, null = null возвращает true.

4b9b3361

Ответ 1

Причина, по которой это по умолчанию, заключается в том, что null действительно не соответствует null в бизнес-смысле. Например, если вы присоединились к заказам и клиентам:

select * from orders o join customers c on c.name = o.customer_name

Не было бы большого смысла сопоставлять заказы с неизвестным клиентом с клиентами с неизвестным именем.

Большинство баз данных позволяют настроить это поведение. Например, в SQL Server:

set ansi_nulls on
if null = null  
    print 'this will not print' 
set ansi_nulls off
if null = null  
    print 'this should print'

Ответ 2

Равенство - это то, что может быть абсолютно определено. Проблема с null заключается в том, что она по своей сути неизвестна. Если вы следуете таблице истинности для трехзначной логики, null в сочетании с любым другим значением null - неизвестно. Запрос SQL "Является ли мое значение равным null?" будет неизвестно каждый раз, даже если значение ввода равно null. Я думаю, что реализация IS NULL дает понять.

Ответ 3

Это языковая семантика.

Null - это отсутствие значения.

is null имеет смысл для меня. В нем говорится: "отсутствует ценность" или "неизвестно". Лично я никогда не спрашивал кого-то, если что-то есть, "равное отсутствию ценности".

Ответ 4

Понятие состоит в том, что NULL не является справедливым значением. Это означает отсутствие значения.

Поэтому переменную или столбец можно проверить только, если она IS NULL, но не если она IS EQUAL TO NULL.

Как только вы откроете арифметические сравнения, вам, возможно, придется бороться с IS GREATER THAN NULL или IS LESS THAN OR EQUAL TO NULL

Ответ 5

NULL неизвестно. Это не правда и не ложно, поэтому, когда вы сравниваете что-либо с неизвестным, единственный ответ "неизвестен". Лучше статья о wikipedia http://en.wikipedia.org/wiki/Null_(SQL)

Ответ 6

Я не могу не чувствовать, что вы все еще не удовлетворены ответами, которые были даны до сих пор, поэтому я подумал, что попробую еще один курс. Дайте пример (нет, я не знаю, почему этот конкретный пример пришел мне в голову).

У нас есть таблица для сотрудников, EMP:

EMP
---
EMPNO           GIVENNAME
E0001           Boris
E0002           Chris
E0003           Dave
E0004           Steve
E0005           Tony

И по какой-то причудливой причине мы отслеживаем, какие цветные штаны каждый сотрудник выбирает носить в определенный день (TROUS):

TROUS
-----
EMPNO       DATE        COLOUR
E0001       20110806    Brown
E0002       20110806    Blue
E0003       20110806    Black
E0004       20110806    Brown
E0005       20110806    Black
E0001       20110807    Black
E0003       20110807    Black
E0004       20110807    Grey

Я мог бы продолжить. Мы пишем запрос, где мы хотим узнать имя каждого сотрудника и какие цветные штаны у них были 7 августа:

SELECT e.GIVENNAME,t.COLOUR
FROM
    EMP e
        LEFT JOIN
    TROUS t
        ON
             e.EMPNO = t.EMPNO and
             t.DATE = '20110807'

И получим набор результатов:

GIVENNAME       COLOUR
Chris           NULL
Steve           Grey
Dave            Black
Boris           Black
Tony            NULL

Теперь этот набор результатов может быть в представлении, или CTE, или что-то еще, и мы, возможно, захотим продолжить задавать вопросы об этих результатах, используя SQL. Какие могут быть некоторые из этих вопросов?

  • Были ли в тот день Дейва и Бориса в темных цветных штанах? (Да, черный == Черный)

  • Были ли Дэйв и Стив в тех же цветах в тот день? (Нет, Черный!= Серый)

  • Были ли в тот день Борис и Тони в одних и тех же цветных брюках? (Неизвестно - мы пытаемся сравнить с NULL, и мы следуем правилам SQL)

  • Были ли Борис и Тони не в тех же цветных штанах в этот день? (Неизвестно - мы снова сравниваем с NULL, и мы следуем правилам SQL)

  • Были ли в тот день Криса и Тони в тех же цветных брюках? (Неизвестно)

Обратите внимание, что вы уже знаете о конкретных механизмах (например, IS NULL), чтобы заставить нужные вам результаты, если вы разработали базу данных, чтобы никогда не использовать NULL в качестве маркера для отсутствия информации.

Но в SQL NULL получили две роли (по крайней мере) - чтобы отметить неприменимую информацию (возможно, у нас есть полная информация в базе данных, а Крис и Тони не появились на работу в тот день или не сделали этого "ношу брюки" ) и отметить недостающую информацию (в этот день появился Крис, у нас просто нет информации, записанной в базе данных в настоящее время)

Если вы используете NULL чисто как маркер неприменимой информации, я предполагаю, что вы избегаете таких конструкций, как внешние соединения.


Мне интересно, что вы добавили NaN в комментарии к другим ответам, не заметив, что NaN и (SQL) NULL имеют много общего. Самое большое различие между ними заключается в том, что NULL предназначен для использования по всей системе, независимо от того, какой тип данных задействован.

Самая большая проблема заключается в том, что вы решили, что NULL имеет одно значение во всех языках программирования, и вы, кажется, чувствуете, что SQL нарушил это значение. Фактически, нуль на разных языках часто имеет тонко разные значения. На некоторых языках это синоним 0. В других нет, поэтому сравнение 0==null преуспеет в одних и не удастся другим. Вы упомянули VB, но VB (при условии, что вы говорите, версии .NET) не имеет значения null. Он имеет Nothing, что опять-таки немного отличается (это эквивалентно в большинстве случаев конструкции С# default(T)).

Ответ 7

Потому что в ANSI SQL значение null означает "неизвестно", что не является значением. Таким образом, он ничем не равен; вы можете просто оценить состояние значения (известное или неизвестное).

Ответ 8

а. Нуль - это не "недостаток значения"

б. Null не является "пустым"

с. Null не является "неустановленным значением"

Все вышесказанное и ни одно из вышеперечисленных.

По техническим правам NULL является "неизвестным значением". Однако, как и неинициализированные указатели в C/С++, вы действительно не знаете, на что вы указываете. В базах данных они выделяют пространство, но не инициализируют значение в этом пространстве.

Итак, это "пустое" пространство в том смысле, что оно не инициализировано. Если вы установите значение NULL, исходное значение останется в этом месте хранения. Если это была изначально пустая строка (например), она останется той.

Это "недостаток значения" в том, что он не был настроен на то, что база данных считает допустимым.

Это "неустановленное значение" в том, что если пространство было просто выделено, значение, которое там никогда не было установлено.

"Неизвестный" - это самое близкое, что мы действительно можем узнать, чего ожидать, когда исследуем NULL.


Из-за этого, если мы попытаемся сравнить это "неизвестное" значение, мы получим сравнение, которое

a) может быть или не быть действительным

b) может или не может быть ожидаемый результат

c) может или не может сбой базы данных.

Итак, системы СУБД (давно) решили, что даже не имеет смысла использовать равенство, когда дело доходит до NULL.

Поэтому "= null" не имеет смысла.

Ответ 9

В дополнение ко всему, что уже было сказано, я хочу подчеркнуть, что то, что вы пишете в своей первой строке, неверно. SQL поддерживает синтаксис "= NULL", но имеет другую семантику, чем "IS NULL" - как видно из самой части документации, с которой вы связаны.

Ответ 10

Я согласен с OP, что

where column_name = null

должен быть синтаксическим сахаром для

where column_name is null

Однако я понимаю, почему создатели SQL хотели сделать различие. В трехзначной логике (ИМО это неправильное обозначение) предикат может возвращать два значения (истинные или ложные) ИЛИ неизвестные, что технически не является значением, а просто способ сказать "мы не знаем, какое из двух значений это является". Подумайте о следующем предикате в терминах трехзначной логики:

A == B

Этот предикат проверяет, является ли A равным B. Здесь выглядит таблица истинности:

    T U F
    -----
T | T U F
U | U U U
F | F U T

Если A или B неизвестны, сам предикат всегда возвращает неизвестный, независимо от того, является ли другой истиной или ложной или неизвестной.

В SQL значение null является синонимом неизвестного. Итак, предикат SQL

column_name = null

проверяет, равно ли значение column_name чему-то, чье значение неизвестно, и возвращает неизвестно независимо от того, является ли column_name истинным или ложным или неизвестным или что-то еще, точно так же, как в трехзначной логике выше. Операции SQL DML ограничены работой в строках, для которых предикат в предложении where возвращает true, игнорируя строки, для которых предикат возвращает false или неизвестно. Поэтому "where column_name = null" не работает ни в одной строке.

Ответ 11

NULL не равен NULL. Он не может равняться NULL. Для них не имеет смысла быть равными.

Несколько способов подумать об этом:

  • Представьте базу данных контактов, содержащую такие поля, как FirstName, LastName, DateOfBirth и HairColor. Если бы я искал записи WHERE DateOfBirth = HairColor, должен ли он когда-либо соответствовать чему-либо? Что, если кто-то DateOfBirth был NULL, а их HairColor тоже? Неизвестный цвет волос не равен никому неизвестному.

  • Позвольте присоединиться к таблице контактов с таблицами покупок и продуктов. Скажем, я хочу найти все случаи, когда клиент купил парик, который был того же цвета, что и их собственные волосы. Поэтому я запрашиваю WHERE contacts.HairColor = product.WigColor. Должен ли я получать совпадения между каждым клиентом, я не знаю цвета волос и продуктов, у которых нет WigColor? Нет, это другое дело.

  • Давайте рассмотрим, что NULL - это другое слово для неизвестного. Каков результат ('Smith' = NULL)? Ответ не является ложным, он неизвестен. Неизвестно, это неверно, поэтому оно ведет себя как ложное. Каков результат (NULL = NULL)? Ответ также неизвестен, поэтому также эффективно ложный. (Это также связано с тем, что объединение строки со значением NULL приводит к тому, что вся строка становится NULL - результат действительно неизвестен.)

Ответ 12

Почему вы не используете функцию isnull?

@where = "where GroupId = "+ isnull(@groupId,"null")