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

на SQL и реляционная теория (C. J. дата, 2009) Глава 4 призывает избегать повторяющихся строк, а также избегать NULL атрибуты данных, которые мы храним. Хотя у меня нет проблем избежать повторяющихся строк, я изо всех сил пытаюсь увидеть, как я могу моделировать данные без использования NULL. Возьмем, к примеру, следующее - Это немного от работы.

у нас есть artist таблица, которая имеет, среди других столбцов,. Это внешний ключ к gender таблица. Однако для некоторых артистов мы не знаем их пола - например, нам дали список новой музыки, в котором нет описаний артиста. Как, без использования NULL предназначен ли он для представления этих данных? Единственное решение, которое я вижу, - добавить новый пол, "неизвестный", к gender таблица.

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

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


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

SELECT s.sno, p.pno
  FROM s, p
 WHERE s.city <> p.city
    OR p.city <> 'Paris'
, возьмем пример, что.город Лондон, и P.город-это Париж. В этом случае London Paris, поэтому запрос true. Теперь возьмем случай, что p.город не Париж, а Инфакт xyz. В этом случае (London xyz) или ( xyz Paris) также верно. Итак, учитывая любые данные-этот запрос верен. Однако, если xyz равен "NULL", сценарий изменяется. В этом случае оба этих выражения не являются ни True , ни ложные, они на самом деле неизвестны. И в этом случае, потому что результат неизвестен, вы не получите все возвращенные строки.

переход от 2-значной логики к 3-значной логике может легко ввести такие ошибки. Infact, я только что представил один на работе, который мотивировал этот самый пост. Я хотел все строки, где type != 0 однако, это на самом деле заканчивается соответствие type == 0 OR type IS NULL - странное поведение.

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

8 ответов


все говорят, и никто, кроме dportas и Walter не может даже понять вопрос. Хорошо, поэтому 95% людей на SO не понимают проблему Null и чувствуют угрозу, потому что их базы данных полны нулей, они хотят преобразовать искателя. Бесценный. Как кто-то может научиться спорить ?

хорошо на вас, для устранения нулей. Я никогда не допускал нулей ни в одну из своих баз данных.

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

на самом деле это не так сложно. Есть три варианта.

  1. вот статья о Как Обращаться С Отсутствующими Информация без использования NULL по H Darwen, это может помочь получить вашу голову вокруг проблемы.

1.1. Шестая Нормальная Форма быть ответом. Но вы не должны нормализовать свой весь база данных в 6NF. Для каждого столбца, который является необязательным, вам нужна дочерняя таблица с главной таблицей, только с PK, который также является FK, потому что это отношение 1::0-1. Кроме PK, единственным столбцом является необязательный столбец.

смотреть на это Модель Данных; AssetSerial на странице 4 классический случай: далеко не всеAssets есть SerialNumbers; но когда они это сделают, я хочу, чтобы они хранили их; что более важно, я хочу убедиться, что они уникальны.

(для людей OO там, кстати, это трехуровневая диаграмма классов в реляционной нотации," наследование таблицы Concwete", ничего особенного, у нас это было 30 лет.)

1.2. Для каждой такой таблицы используйте представление, чтобы предоставить форму таблицы 5NF. Конечно, используйте Null (или любое значение, подходящее для столбца), чтобы определить отсутствие столбца для любой строки. Но не Обновление через представление.

1.3 не используйте прямые соединения для захвата столбца 6NF. Не используйте внешние соединения (и попросите сервер заполнить Null для отсутствующих строк). Используйте подзапрос для заполнения столбца и укажите значение, которое вы хотите вернуть для отсутствующего значения (за исключением Oracle, потому что его обработка подзапроса еще хуже, чем его обработка набора). Например. и просто УГ. вы можете преобразовать числовой столбец в строку, и использовать "пропавших без вести" пропавших строки.

когда вы не хотите идти так далеко (6NF), у вас есть еще два варианта.
.
2. Можно использовать заменители Null. Я использую CHAR (0) для символов colomns и 0 для числовых. Но я не допускаю этого для ФКС. Очевидно, вам нужно значение, которое находится за пределами нормального диапазона данных. Это не допускает трехзначной логики.
.
3. В дополнение к (2) для каждого столбца с нулевым значением необходим логический индикатор. Для примера , в Индикатор будет чем-то вроде SexIsMissing или SexLess (извините). Это позволяет очень плотно трехзначную логику. Многим людям в этом 5% нравится, потому что БД остается на 5NF (и меньше таблиц); столбцы с отсутствующей информацией загружаются значениями, которые никогда не используются; они используются только если индикатор false. Если у вас есть корпоративная БД, вы можете обернуть ее в функцию и всегда использовать UDF, а не необработанный столбец.

конечно, во всех случаях, вы никогда не сможете уйти от написания кода это необходимо для обработки недостающей информации. Является ли это ISNULL(), или подзапрос для столбца 6NF, или индикатор для проверки перед использованием значения, или UDF.

если Null имеет определенное значение ... тогда это не Null ! По определению, Null-это неизвестное значение.


Итак, как вы проектируете без нулей? Это был первоначальный вопрос.

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

Итак, в случае "DateOfDeath" у нас есть таблица с двумя столбцами, а именно PersonId и DateOfDeath. Идентификатор ссылки PersonId в таблице Persons. Если есть нет DateOfDeath для хранения, мы не храним строку. Конец дискуссии.

Если вы сделаете внешнее соединение между этим и таблицей Persons, вы получите NULL для DateOfDeath везде, где не было строки. И если вы используете это в предложении where, вы получите обычное озадачивающее поведение в отношении 3-значной логики. Если вы выполните внутреннее соединение, строки, для которых нет DateOfDeath, просто исчезнут из соединения.

конструкция которая позволяет каждый столбец быть не Null принудительно называется шестой нормальной формой.

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


довольно просто, сохраняя только известную информацию - другими словами, предположение о закрытом мире. Стремитесь быть, по крайней мере, в Boyce Codd / пятой нормальной форме, и вы не ошибетесь.


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


требуются нули - нет необходимости их заменять

определение ENITRE NULL заключается в том, что его неизвестно - просто замена этого произвольным типом делает то же самое, так почему?

комментарии ниже:

просто попробовал это - ни Правда:

declare @x char
set @x = null

if @x = @x
begin
select 'true'
end

if @x <> @x
begin
select 'false'
end

Я могу только принять это, чтобы означать, что, поскольку null неизвестно, то нельзя сказать, что он равен или не равен - следовательно, оба утверждения ложны


NULL может / должен использоваться до тех пор, пока:

A) у вас есть бизнес-причины. Например, в таблице платежей,NULL значение оплаты будет означать, что он никогда не был оплачен. А 0.00 значение оплаты означало бы, что мы намеренно ничего не платили. Для медицинских карт a NULL значение для измерения кровяного давления будет означать, что вы не приняли BP, a 0 значение будет означать, что пациент мертв. Это значительное различие, и необходимые в некоторых приложениях.

B) ваши запросы на этот счет. Если вы понимаете влияние NULL on IN, EXISTS, операторы неравенства (как вы указали в OP) и т. д. тогда это не должно быть проблемой. Если у вас есть NULL теперь в ваших таблицах и не хотите значения для определенных приложений, вы можете использовать представления и либо COALESCE или ISNULL для заполнения различных значений, если исходная таблица имеет NULL.

EDIT:

для решения вопросов OP о неравенствах/равенствах" реального мира " с помощью NULL, Это отличный пример, который я иногда использую.

вы находитесь на вечеринке с 3 другими людьми. Вы знаете, что одного человека зовут Джон, но не знаете других.

логически, ответ на вопрос" сколько людей зовут Джо " неизвестен или NULL. В SQL это было бы что-то как

SELECT name FROM party where NAME = 'Joe' вы не получите строк, так как вы не знаете их имен. Может, это Джо, а может, и нет.

ваше неравенство будет:

SELECT name from party where NAME <> 'Joe' вы получите только возвращаемое значение для "John", так как имя Джона-это все, что вы знаете. Другие люди могут быть или не быть Джо, но у вас нет способа узнать.


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

для вашей конкретной проблемы, касающейся пола:

  • вы уверены, что хотите гендерную таблицу и нести расходы на дополнительное соединение для каждого запроса? Для простых перечисляемых типов вполне разумно сделать поле int и определить 1=мужской, 2=женский, NULL=неизвестно.

Не разрешайте определять столбец как NULL, если это вообще возможно. Для меня это не имеет ничего общего с бизнес-правилом того, что вы хотите, чтобы NULL означало, что это связано с disk I\O.

в SQL Server столбец nullable, скажем, символ 10, будет принимать один бит в растровом изображении, когда null и 10 байт, когда не nullable. Итак, как наличие null повреждает дисковый ввод-вывод, так как это больно, когда значение вставляется в столбец, где раньше был null. Поскольку SQL не зарезервировал место в строке нет места, чтобы просто поместить значение, поэтому SQL Server должен перемещать данные, чтобы освободить место. Разбиение страницы, фрагментация, обновление МПОГ, если это куча и т. д. Все повредили дисковый ввод-вывод

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