Некоторые, в то время как назад, я прочитывал книгу SQL и Реляционная Теория C. J. Дата. Автор известен за критику трехзначной логики SQL (3VL).1),
Автор делает некоторые сильные стороны того, почему 3VL должен избежаться в SQL, однако он не обрисовывает в общих чертах, как модель базы данных была бы похожа, если бы nullable столбцы не были позволены. Я думал на этом некоторое время и предложил следующие решения. Если бы я пропустил другие проектные решения, то я хотел бы услышать о них!
1) Критический анализ даты SQL 3VL был в свою очередь подвергнут критике также: посмотрите данная статья Claude Rubinson (включает исходный критический анализ C. J. Дата).
Таблица Example:
Как пример, возьмите следующую таблицу, где у нас есть один nullable столбец (DateOfBirth
):
# +-------------------------------------------+
# | People |
# +------------+--------------+---------------+
# | PersonID | Name | DateOfBirth |
# +============+--------------+---------------+
# | 1 | Banana Man | NULL |
# +------------+--------------+---------------+
Опция 1: эмуляция NULL
через флаг и значение по умолчанию:
Вместо того, чтобы делать столбец nullable, указано любое значение по умолчанию (например. 1900-01-01
). Дополнительное BOOLEAN
столбец укажет ли значение в DateOfBirth
должен просто быть проигнорирован или содержит ли это на самом деле данные.
# +------------------------------------------------------------------+
# | People' |
# +------------+--------------+----------------------+---------------+
# | PersonID | Name | IsDateOfBirthKnown | DateOfBirth |
# +============+--------------+----------------------+---------------+
# | 1 | Banana Man | FALSE | 1900-01-01 |
# +------------+--------------+----------------------+---------------+
Опция 2: Превращение nullable столбца в отдельную таблицу:
nullable столбец заменяется новой таблицей (DatesOfBirth
). Если запись не будет иметь данных для того столбца, то в новой таблице не будет записи:
# +---------------------------+ 1 0..1 +----------------------------+
# | People' | <-------> | DatesOfBirth |
# +------------+--------------+ +------------+---------------+
# | PersonID | Name | | PersonID | DateOfBirth |
# +============+--------------+ +============+---------------+
# | 1 | Banana Man |
# +------------+--------------+
В то время как это походит на лучшее решение, это возможно привело бы ко многим таблицам, к которым нужно присоединиться для единого запроса. С тех пор OUTER JOIN
s не будет позволен (потому что они представили бы NULL
в набор результатов), все необходимые данные больше не могли возможно выбираться только с единым запросом как прежде.
Вопрос: Есть ли любые другие опции для устранения NULL
(и если так, каковы они)?
Я видел, как коллега Дейта Хью Дарвен обсуждал этот вопрос в отличной презентации «Как обрабатывать отсутствующую информацию без использования NULL», которая доступна на веб-сайте Третьего манифеста .
Его решение является вариантом вашего второго подхода. Это шестая нормальная форма с таблицами, содержащими как дату рождения, так и идентификаторы, где она неизвестна:
# +-----------------------------+ 1 0..1 +----------------------------+
# | People' | <-------> | DatesOfBirth |
# +------------+----------------+ +------------+---------------+
# | PersonID | Name | | PersonID | DateOfBirth |
# +============+----------------+ +============+---------------+
# | 1 | Banana Man | ! 2 | 20-MAY-1991 |
# | 2 | Satsuma Girl | +------------+---------------+
# +------------+----------------+
# 1 0..1 +------------+
# <-------> | DobUnknown |
# +------------+
# | PersonID |
# +============+
# | 1 |
# +------------+
Выбор из людей требует объединения всех трех таблиц, включая шаблон для указания неизвестных дат рождения.
Конечно, это несколько теоретически. Состояние SQL в наши дни все еще недостаточно развито, чтобы справиться со всем этим. Презентация Хью покрывает эти недостатки. Одна вещь, которую он упоминает, не совсем верна: некоторые разновидности SQL действительно поддерживают множественное присваивание - например, синтаксис Oracle INSERT ALL .
Я не читал, но есть статья под названием Как обрабатывать недостающую информацию с помощью S-by-C в Третьем манифесте веб-сайт, которым руководят Хью Дарвен и Си Джей Дэйт. Это написано не Си Джей Дейтом, но я предполагаю, что, поскольку это одна из статей на этом веб-сайте, она, вероятно, похожа на его мнение.
Альтернативой может быть модель значение атрибута объекта :
entity attribute value
1 name Banana Man
1 birthdate 1968-06-20
Если дата рождения неизвестна, вы просто опустите ее строку.
Вариант 3: Обязанность автора записи:
CREATE TABLE Person
(
PersonId int PRIMARY KEY IDENTITY(1,1),
Name nvarchar(100) NOT NULL,
DateOfBirth datetime NOT NULL
)
Зачем искажать модель, чтобы разрешить нулевое представление, если ваша цель - их устранить?