Должен ли я разрешить нулевые значения в схеме БД? - PullRequest
27 голосов
/ 08 июня 2009

Я знаю, что логически, в некоторых случаях значения NULL имеют смысл в схеме БД, например, если некоторые значения не были заданы. Тем не менее, работа вокруг DBNull в коде имеет тенденцию быть королевской болью. Например, если я отрисовываю представление и хочу увидеть строку, я не ожидал бы, что значение будет пустой строкой, а не «Null», и я ненавижу кодировать этот сценарий.

Кроме того, это облегчает выполнение запросов. По общему признанию, вы можете сделать "foo is not null" очень легко, но для младших разработчиков SQL это интуитивно понятно, если вы не сможете использовать "foo! = Null" (и да, я знаю об опциях отключения нулей ANSI и т. Д. , но это определенно НЕ проще, и мне не нравится работать вне стандарта).

Какая веская причина для того, чтобы иметь / разрешать нули в схеме базы данных?

Ответы [ 15 ]

41 голосов
/ 08 июня 2009

Наиболее значимой причиной для разрешения NULLS является отсутствие разумной альтернативы. Логически, значение NULL представляет «неопределенное». Из-за отсутствия NULLS вы в конечном итоге попытаетесь указать «фиктивное» значение там, где результат не определен, а затем вам придется учитывать указанное «фиктивное» значение во ВСЕХ логики вашего приложения.

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

11 голосов
/ 09 июня 2009

C.J. Дата в своей книге «SQL и теория отношений» (2009: O'Reilly; ISBN 978-0-596-52306-0) занимает очень сильную позицию против NULL. Он демонстрирует, что наличие NULL в SQL дает неправильные ответы на определенные запросы. (Аргумент не применяется к самой реляционной модели, поскольку реляционная модель не допускает значения NULL.)

Я постараюсь обобщить его пример словами. Он представляет таблицу S с атрибутами SNO (номер поставщика) и город (город, в котором находится поставщик) и одну строку: (S1, Лондон). Также таблица P с атрибутами PNO (номер детали) и City (город, в котором производится деталь) и одной строкой: (P1, NULL). Теперь он выполняет запрос «Получить (SNO, PNO) пары, в которых либо города-поставщики, либо города-детали отличаются, либо город-часть не является Парижем (или оба)».

В реальном мире P1 создается в городе, который является или не является Парижем, поэтому запрос должен возвращаться (S1, P1), потому что город-часть либо является Парижем, либо не Парижем. (Простое присутствие P1 в таблице P означает, что с деталью связан город, даже если он неизвестен.) Если это Париж, то города-поставщики и детали различаются. Если это не Париж, то часть города не является Парижем. Однако, по правилам трехзначной логики, ('London' <> NULL) оценивается как UNKNOWN, (NULL <> 'Paris') оценивается как UNKNOWN, а UNKNOWN OR UNKNOWN уменьшается до UNKNOWN, что не является ИСТИННЫМ (и не FALSE либо), и поэтому строка не возвращается. Результатом запроса «ВЫБРАТЬ S.SNO, P.PNO ИЗ S, P, ГДЕ S.CITY <> P.CITY OR P.CITY <> 'Paris'" является пустая таблица, неправильный ответ.

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

P.S. Также верно, что вы можете использовать SQL как нечто отличное от реляционной базы данных. Он может делать много вещей.

6 голосов
/ 08 июня 2009

Какая веская причина для того, чтобы иметь / разрешать нули в схеме базы данных?

С точки зрения теории, наличие NULL означает, что значение не определено для столбца.

Используйте его там, где вам нужно, чтобы сказать " Я не знаю / мне все равно ", чтобы ответить на вопрос " Какова стоимость этого столбца? "

А вот несколько советов с точки зрения производительности:

  • В Oracle, NULL не индексируются. Вы можете сохранить пространство индекса и ускорить запросы, используя NULL для значений, которые не нужно индексировать.
  • В Oracle, конечные NULL не занимают места.
  • В отличие от нулей, NULL можно безопасно разделить на.
  • NULL вносят вклад в COUNT(*), но не вносят вклад в COUNT(column)
4 голосов
/ 08 июня 2009

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

например, если у вас есть и дата окончания, у вас может возникнуть желание ввести datetime.maxvalue как значение по умолчанию вместо нуля. он полностью действителен, но вы должны принять во внимание отчетность по этому вопросу и тому подобное.

3 голосов
/ 09 июня 2009

В теории нет разницы между теорией и практикой. На практике есть.

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

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

Подходящими кандидатами для столбцов, допускающих значение NULL, являются те, в которых помимо необязательных данных вы никогда не используете столбец в условии сравнения в предложении WHERE или HAVING. Хотите - верьте, хотите - нет, но внешние ключи часто работают нормально с NULL в них, чтобы показать случай отсутствия связи. INNER JOINS удалит NULL вместе со строками, которые их содержат.

Когда значение часто используется в логических условиях, лучше всего спроектировать так, чтобы значения NULLS не возникали. В противном случае вы можете получить загадочный результат, что в SQL значение NOT NOTKNOWN равно UNKNOWN. Это вызвало ошибки у многих людей до вас.

2 голосов
/ 08 июня 2009

Как правило, если вы разрешите NULL для столбца в базе данных, это значение NULL будет иметь отдельное значение , означающее в отношении структуры самой базы данных. Например, в схеме базы данных StackOverflow значение NULL для столбца ParentId или Tags в таблице Post указывает, является ли сообщение вопросом или ответом. Просто убедитесь, что в каждом случае значение хорошо задокументировано.

Теперь ваша конкретная жалоба касается обработки этих значений в клиентском коде. Есть два способа смягчить проблему:

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

  • В остальных случаях вы, как правило, можете использовать функции, такие как COALESCE () или ISNULL (), для возврата чего-то, что легче обрабатывать.

1 голос
/ 08 июня 2009

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

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

1 голос
/ 08 июня 2009

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

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

Если вы не используете нули, потому что ваши младшие разработчики не понимают их должным образом, это означает, что у вас есть большая проблема, чем нули. Любой разработчик, который не понимает, как получить доступ к данным, содержащим нулевые значения, должен пройти базовое обучение SQL. Это так же глупо, как не использовать триггеры для обеспечения соблюдения правил целостности данных, потому что разработчики забывают смотреть на них, когда есть проблема, или не используют объединения, потому что разработчики не понимают их или используют select *, потому что разработчики слишком ленивы, чтобы добавлять имена полей.

1 голос
/ 08 июня 2009

Ноль полезен, когда вам нужно указать, что значения вообще нет.

Вместо этого вы можете использовать магическое число, но оно более интуитивно понятно для обработки нулей, чем для обработки магических значений, и легче запомнить, какое значение обрабатывать. (Хм ... это было -1 или 99999 или 999999, которое было магической ценностью ...?)

Кроме того, магические ценности не обладают какой-либо реальной магией, и в любом случае нет надежных средств защиты от использования этого значения. Компьютер не знает, что вы не можете умножить 42 на -1, потому что -1 оказывается неразумным значением в этой ситуации, но он знает, что вы не можете умножить 42 на ноль.

Для текстового значения пустая строка может работать как «без значения», но даже здесь есть некоторые недостатки. Например, если в поле три пробела, не всегда можно визуально отличить пустую строку, но это разные значения.

0 голосов
/ 17 июля 2012

Когда есть объект, который не имеет значения для своего атрибута, тогда мы используем нулевое значение. Нулевое значение не равно 0, но это ничто. Один из примеров - большинство корейских имен не имеют отчества. Если есть атрибут name с именем, отчеством и фамилией, следует указать специальное значение null.

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