Я не могу не чувствовать, что вы все еще не удовлетворены ответами, которые были даны до сих пор, поэтому я подумал, что попробую еще один прием. Давайте рассмотрим пример (нет, я понятия не имею, почему этот конкретный пример пришел мне в голову).
У нас есть стол для сотрудников, 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) нет нуля. Он имеет Nothing
, что опять-таки немного отличается (это в большинстве случаев эквивалентно конструкции C # default(T)
).