Подтвердить что ты не робот

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

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

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

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

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

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


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

SELECT s.sno, p.pno
  FROM s, p
 WHERE s.city <> p.city
    OR p.city <> 'Paris'

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

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

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

4b9b3361

Ответ 1

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

Хорошо, что ты выбрал нули. Я никогда не разрешал Nulls в любой из моих баз данных.

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

На самом деле это не так сложно. Существует три альтернативы.

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

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

(Для людей OO, кстати, это трехуровневая диаграмма классов в Relational notation, "Concwete Table Inheritance", неважно, у нас было это на 30 лет.)

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

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

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

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

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

Ответ 2

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

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

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

Если вы выполняете ВНЕШНЮЮ СОБСТВЕННОСТЬ между этой и личностью, вы получите NULL для DateOfDeath везде, где не было строки. И если вы используете это в предложении where, вы получите обычное недоумение в отношении 3-значной логики. Если вы выполняете INNER JOIN, строки, для которых нет DateOfDeath, просто исчезнут из соединения.

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

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

Ответ 3

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

Ответ 4

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

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

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

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

declare @x char
set @x = null

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

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

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

Ответ 5

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

Ответ 6

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

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

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

EDIT:

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

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

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

SELECT name FROM party where NAME = 'Joe' У вас не будет строк, так как вы не знаете их имен. Они могут быть или не быть Джо.

Ваше неравенство было бы следующим:

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

Ответ 7

Многие люди задавали себе эти вопросы.

Помогает ли слово из автора?

ИЗМЕНИТЬ Кроме того, поскольку dportas любезно предоставлено в комментариях, эти показания могут быть интересными

НА НИЧЕГО, ЧТО НЕПРАВИЛЬНО С NULL
НИЧЕГО НЕ ОБРАТИТЬСЯ: ПАРАМЕТРЫ
МНОГО АДО О НИЧЕГО
ЗАКЛЮЧИТЕЛЬНЫЙ НУЛЛ В КОФИНЕ: ЛОГИЧНО ПРАВИЛЬНОЕ РЕШЕНИЕ ДЛЯ НЕИСПРАВНОСТИ ДАННЫХ

Ответ 8

Я не согласен с автором и утверждаю, что NULL на самом деле является ПРАВИЛЬНЫМ способом обработки отсутствующих данных для дополнительных полей. Фактически, это причина, по которой NULL существует вообще...

Для вашей конкретной проблемы с полом:

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

Ответ 9

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

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

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