2009-11-12 2 views
22

Я видел это во многих полях в БД из проекта, над которым я работал, где столбец будет определен не null, но будет иметь пустую строку в качестве значения по умолчанию. в чем смысл этого? Если вы допустите пустую строку, почему бы просто не разрешить поле null?В чем смысл «NOT NULL DEFAULT»?

ответ

36

NULL имеют особое поведение : сравнение чего-либо с NULL дает вам NULL, что является чем-то иным, чем false или 0. Это означает «неизвестно».

Например, возьмем эту таблицу:

user_id | gender 
------------------ 
1  | NULL 
2  | 'M' 
3  | 'F' 
4  | 'F' 

SELECT * FROM mytable WHERE gender = 'M' вернет 1 строку, как и ожидалось

SELECT * FROM mytable WHERE gender != 'M' вернет 2 строки, а не 3 строк.

SELECT * FROM mytable WHERE gender != 'M' OR gender IS NULL вернет ожидаемые 3 строки.


Edit: Для некоторых приложений, использующих 0 (или, не дай Бог, еще один «магическое число») вместо NULL даже не рекомендуется (единицы или точные значения не имеют значения в данном примере):

Date  | Temperature 
-------------------------- 
2010-01-01 | 10   
2010-01-02 | 4 
2010-01-03 | 0 
2010-01-04 | -22 
2010-01-05 | -45 
2010-01-06 | NULL 
2010-01-07 | -34 

Здесь NULL от 6 января означает «значение неизвестно» - возможно, потому, что температура была настолько низкой, что датчик термометра прекратил отвечать.Однако это совершенно другое значение, чем 3 января, когда температура была 0, то есть 0 градусов.

Кроме того, как отмечает @Bill Karwin, ведет себя значение NULL, специально в совокупности функций (COUNT, SUM, AVG и т.д.): вычисление AVG(Temperature) на приведенных выше данных даст вам -14.5, так как строка NULL, игнорируются.

+0

Я понятия не имел, что это будет так! Я принимаю это, так как это прекрасный пример использования нуля. – GSto

+4

+1 Также стоит отметить, что NULL пропускается для большинства совокупных функций. Вероятно, вы не хотите считать NULL равным нулю для 'SELECT AVG (Temperature)', потому что это исказит ваш результат. Таким образом, NULL имеет полезную цель. –

+0

См. Также http://vincedasta.com/p/bad-data-guide/ для некоторого контекста. – Piskvor

0

Потому что иногда, на некоторых языках, а также «выбрать» запрос даст вам строкуNULL, и вы должны проверить, если это настоящая строка с содержанием «NULL» или это действительно пустой.

С «» это самый простой (ИМХО)

+2

Я надеюсь, что я понял, что ... на какие языки вы имеете в виду? – Thomas

+3

Я уверен, что это не так. В SQL вы можете проверить «WHERE MyField IS NULL», который отличается от «WHERE MyField =« NULL ». Когда вы сравниваете результаты на вашем языке программирования, обычно существует способ проверки нулей базы данных. В .NET база данных null представлена ​​как DBNull.Value. – Richard

11

утратившим «» не одно и то же, так что нет никакого противоречия.

Какое семантическое значение null/"" зависит от человека и часто является «религиозным» вопросом. Для некоторых людей в некоторых схемах, конечно, они могут быть одинаковыми, но они не обязательно должны быть. Например, «" может означать, что я явно спросил пользователя для ввода, и они решили ввести ничего ", в то время как нуль может означать" я даже не просил ввода ".

+2

Комментарий к этому вопросу, который может быть религиозным вопросом, поднимает вопрос - опыт разработчиков и опыт могут сыграть свою роль. Следующие примеры ведут себя по-разному на разных языках: '' == null, "" == null, 0 == null, "" === null. С некоторыми у вас есть явные проверки типов (например, String.Empty или === операторы или strcmp()), и легко ошибиться. Различие на некоторых языках намного яснее, чем в других, - некоторые языки сценариев, в частности, делают жизнь сложнее других (например, Perl особенно тонко зла в этом отношении). –

0

Мы не разрешаем null, потому что программный доступ к полю из datatable с использованием значения DBnull вызывает исключение, в то время как пустая строка имеет значение и, следовательно, не является ошибкой.

+0

Является ли это специфическим для некоторого интерфейса? Доступ к нулевому значению в MySQL не вызывает никаких проблем. – gnud

+0

Я считаю, что он ссылается на потребление поля на стороне приложения. VB Classic/.NET интерпретирует поле NULL как DBNull, что может привести к исключению при передаче без предварительной проверки того, что значение не является DBNull. –

+0

Спасибо Стейси, да, это то, что я предлагал. Если вы загрузили свои данные в набор данных или datatable в приложении и захотели присвоить значение поля с нулевым значением переменной, сначала вам нужно проверить, является ли это поле DBNull. Если значение не равно нулю, вы можете безопасно получить доступ к полю без проверки или возможности исключения. – Kevin

4

Существует разница между нулевым значением и пустой строкой - по крайней мере, в SQL.

SELECT LENGTH('tata'); 
4 

SELECT LENGTH(NULL); 
NULL 

SELECT LENGTH('tata')-LENGTH(''); 
4 

SELECT LENGTH('tata')-LENGTH(NULL); 
NULL 
+2

«по крайней мере, в MySQL» => «по крайней мере в SQL» –

+0

Правда, правда. Исправлена. – gnud

1

Большинство языков программирования, которые взаимодействуют с базой данных, изначально не поддерживает NULL, который работает так, как это делает в базе данных. Например, в C#, null <> DbNull.Value. В VB большинство типов данных не могли справиться с нулевой семантикой, например. вы не могли сохранить нуль в Дате или Int и т. д. Уменьшая количество нулей, которые видят клиентские программы, тем меньше головных болей. В случае VB закрывается то, что означает null для строк, это Empty, что является чем-то более близким к неинициализированному, не совсем то же, что и NULL в смысле «неизвестно»

0

В дополнение к тому, что упомянуто @Piskvor, эта практика также существует для того, чтобы предотвратить некоторые потенциальные NullPointerExceptions в логике приложения при наполнении бобы/объекты и т.д. после чтения из БД