Нули в реляционной базе данных в порядке? - PullRequest
68 голосов
/ 02 октября 2008

Существует точка зрения, что нулевые значения не должны быть разрешены в реляционной базе данных. То есть атрибут таблицы (столбец) не должен разрешать нулевые значения. Исходя из опыта разработки программного обеспечения, я действительно не понимаю этого. Кажется, что если значение null допустимо в контексте атрибута, то это должно быть разрешено. Это очень распространено в Java, где ссылки на объекты часто бывают нулевыми. Не имея большого опыта работы с базами данных, мне интересно, что я что-то здесь упускаю.

Ответы [ 33 ]

67 голосов
/ 02 октября 2008

Нули рассматриваются негативно с точки зрения нормализации базы данных. Идея состоит в том, что если значение может быть ничем, тогда вам действительно следует разбить его на другую разреженную таблицу, чтобы вам не требовались строки для элементов, которые не имеют значения.

Необходимо убедиться, что все данные действительны и оценены.

В некоторых случаях полезно иметь нулевое поле, особенно, если вы хотите избежать еще одного объединения по соображениям производительности (хотя это не должно быть проблемой, если ядро ​​базы данных настроено правильно, за исключением исключительных сценариев высокой производительности .)

-Adam

38 голосов
/ 02 октября 2008

Один аргумент против нулей в том, что они не имеют четко определенной интерпретации. Если поле пустое, это можно интерпретировать как любое из следующего:

  • Значение «Ничего» или «Пустой набор»
  • Нет значения, которое имеет смысл для этого поля.
  • Значение неизвестно.
  • Значение еще не введено.
  • Значение представляет собой пустую строку (для баз данных, которые не различают пустые и пустые строки).
  • Некоторое специфичное для приложения значение (например, «Если значение равно нулю, используйте значение по умолчанию».)
  • Произошла ошибка, в результате которой поле имеет нулевое значение, а в действительности это не должно.

Некоторые разработчики схем требуют, чтобы все значения и типы данных имели четко определенные интерпретации, поэтому нулевые значения являются плохими.

32 голосов
/ 02 октября 2008

Нулевые маркеры в порядке. Действительно, они есть.

27 голосов
/ 02 октября 2008

Это зависит.

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

Например, столбец типа NUM_CHILDREN - что вы делаете, если не знаете ответа - это должно быть NULL. На мой взгляд, нет другого лучшего варианта для дизайна этого столбца (даже если у вас есть флаг, чтобы определить, является ли столбец NUM_CHILDREN действительным, вам все равно нужно иметь значение в этом столбце).

С другой стороны, если вы не разрешаете NULL s и имеете специальные зарезервированные значения для определенных случаев (вместо флагов), например, -1 для числа детей, когда оно действительно неизвестно, вы должны обратиться к этим аналогичным образом, с точки зрения соглашений, документации и т. д.

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

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

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

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

17 голосов
/ 29 октября 2008

Есть несколько различных возражений против использования NULL. Некоторые из возражений основаны на теории баз данных. В теории нет разницы между теорией и практикой. На практике есть.

Это правда, что полностью нормализованная база данных может вообще обходиться без NULLS. Любое место, где необходимо пропустить значение данных, - это место, где можно пропустить всю строку без потери информации.

На практике декомпозиция таблиц в такой степени не служит большой полезной цели, и программирование, необходимое для выполнения простых операций CRUD над базой данных, становится более утомительным и подверженным ошибкам, а не меньшим.

Есть места, где использование NULLS может вызвать проблемы: по сути, они вращаются вокруг следующего вопроса: что в действительности означает отсутствие данных? Все, что NULL действительно передает, - это то, что в данном поле не хранится значение. Но программисты логических выводов, опирающиеся на отсутствующие данные, иногда неверны, и это вызывает много проблем.

Данные могут отсутствовать в местоположении по разным причинам. Вот некоторые из них:

  1. Данные неприменимы в этом контексте. например имя супруга для одного человека.

  2. Пользователь формы ввода данных оставил поле пустым, и приложение не требует ввода в поле.

  3. Данные копируются в базу данных из другой базы данных или файла, и в источнике отсутствовали данные.

  4. Существует необязательное отношение, закодированное во внешнем ключе.

  5. В базе данных Oracle была сохранена пустая строка.

Вот несколько советов о том, когда следует избегать NULLS:

Если в ходе обычного ожидаемого программирования разработчики запросов должны написать много кода ISNULL, NV, COALESCE или аналогичного кода, чтобы заменить допустимое значение на NULL. Иногда лучше сделать замену во время хранения, при условии, что хранится «реальность».

Если счетчики могут быть отключены, потому что были подсчитаны строки, содержащие NULL. Часто этого можно избежать, просто выбрав count (MyField) вместо count (*).

Вот одно место, где вам, к счастью, лучше привыкнуть к NULLS и программировать соответственно: всякий раз, когда вы начинаете использовать внешние объединения, такие как LEFT JOIN и RIGHT JOIN. Весь смысл внешнего соединения, в отличие от внутреннего, состоит в том, чтобы получать строки, когда некоторые совпадающие данные отсутствуют. Недостающие данные будут представлены как NULLS.

Мой итог: не отвергайте теорию, не понимая ее. Но узнайте, когда отступать от теории, а также как ей следовать.

16 голосов
/ 02 октября 2008

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

Если что-то «не существует», вам следует использовать NULL вместо пустой строки или другого типа флага.

11 голосов
/ 02 октября 2008

Вместо того, чтобы писать все вопросы о NULL, и tristate против булевой логики и т. Д. - я предложу этот содержательный совет:

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

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

9 голосов
/ 02 октября 2008

Существует другая альтернатива использованию "N / A" или "N / K" или пустой строки - отдельная таблица.

например. если мы можем знать или не знать номер телефона клиента:

CREATE TABLE Customer (ID int PRIMARY KEY, Name varchar(100) NOT NULL, Address varchar(200) NOT NULL);
CREATE TABLE CustomerPhone (ID int PRIMARY KEY, Phone varchar(20) NOT NULL, CONSTRAINT FK_CustomerPhone_Customer FOREIGN KEY (ID) REFERENCES Customer (ID));

Если мы не знаем номер телефона, мы просто не добавляем строку во вторую таблицу.

8 голосов
/ 02 октября 2008

Я бы сказал, что Nulls обязательно должен использоваться. Нет другого правильного способа представить недостаток данных. Например, было бы неправильно использовать пустую строку для представления отсутствующей строки адреса, или было бы неправильно использовать 0 для представления отсутствующего элемента данных о возрасте. Потому что и пустая строка, и 0 являются данными. Null - лучший способ представить такой сценарий.

7 голосов
/ 22 апреля 2009

Не стоит недооценивать сложность, которую вы создаете, сделав поле NULLable. Например, следующее предложение where выглядит так, как будто оно будет соответствовать всем строкам (биты могут быть только 1 или 0, верно?)

where bitfield in (1,0)

Но если битовое поле NULLable, оно пропустит некоторые. Или возьмите следующий запрос:

select * from mytable
where id not in (select id from excludetable)

Теперь, если исключаемая таблица содержит ноль и 1, это означает:

select * from mytable
where id <> NULL and id <> 1

Но «id <> NULL» имеет значение false для любого значения id, поэтому это никогда не вернет никаких строк. Это удивляет даже опытных разработчиков баз данных.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...