Использование нулевых значений в связанных таблицах с ограничениями внешнего ключа

У меня есть следующие таблицы:

Cateogories

  • CategoryID (интервал) первичный ключ
  • CategoryName (varchar)

Объекты

  • ItemID (интервал) первичный ключ
  • CategoryID (интервал)
  • ItemName (varchar)

Существует ограничение внешнего ключа на Объекты. CategoryID. Существует шанс что, когда новый объект создается, что не будет никакой присвоенной категории.

Лучше установить Объекты. CategoryID для разрешения аннулирует, и соглашение с пустыми указателями в моем коде ИЛИ лучше не позволить аннулирует, установило CategoryID по умолчанию на 1, и создает фиктивную запись в таблице Categories под названием "Некатегоризированный" и затем имеет дело с той фиктивной категорией в моем коде?

5
задан jpshook 7 January 2010 в 13:58
поделиться

7 ответов

Логически правильным способом было бы, чтобы столбец CategoryID был NULL, когда нет Category для данного элемента.

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

.
7
ответ дан 13 December 2019 в 19:28
поделиться

Это зависит от:

Если ваши объекты действительно не имеют категории, то я бы разрешил NULLs, так как это то, что у вас есть: нет CategoryId.

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

Если вы хотите отобразить все элементы и показать категории, вам лучше знать, что есть элементы без категории, поэтому в этом случае вы должны использовать LEFT JOIN.

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


Если вы хотите, чтобы категория Uncategorized рассматривалась так же, как и другие категории (перечислите их с другими категориями, подсчитайте присвоенные им элементы, выберите их в списках/открытиях), то она должна получить свою собственную категорию, а элемент.CategoryId должен быть NOT NULL.

.
2
ответ дан 13 December 2019 в 19:28
поделиться

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

Идите за логической последовательностью, иначе вы окажетесь в беспорядке. Если это означает создание категории "Разное", то сделайте это и убедитесь, что (a) пользователи знают, когда ее использовать и (b) о ней регулярно сообщается, чтобы удостовериться, что элементы правильно распределены по категориям.

.
1
ответ дан 13 December 2019 в 19:28
поделиться

Для простых таблиц поиска такого типа почти всегда лучше запретить NULL и иметь неизвестное значение в таблице поиска.

Почему?

  • Потому что спецификации ANSI NULL непоследовательны и очень сложны. Работа с нулями значительно повышает вероятность появления дефектов кодирования и требует гораздо больше кода для написания
  • Потому что мало кто из разработчиков действительно понимает, как NULL работают во всех сценариях
  • Потому что это хорошо упрощает вашу модель и запросы. Вы можете красиво соединять вещи вместе с внутренними соединениями в любом направлении с помощью очень простого sql.

Однако, несколько предостережений:

  • Вам может понадобиться более одного "фиктивного" значения: одно для "неизвестного" и другое для "не назначенного". Конечно, NULL объединяет оба значения в одно, так что если вы это сделаете, то выйдете за рамки минимального стандарта
  • Иногда вы будете иметь дополнительные неключевые атрибуты, которые либо должны быть нулевыми, либо нести значения типа 'n/a' для фиктивных строк. Для сильно денормализованных поисковых таблиц (например, размеры склада) вам, вероятно, понадобятся nulls, допускающие использование этих столбцов, так как 'n/a' плохо работает для временных меток, сумм и т.д.
  • Если вы примените эту технику к более чем простым поисковым таблицам, то это значительно усложнит ваш дизайн. Не делайте этого.
1
ответ дан 13 December 2019 в 19:28
поделиться

SQL NULL - хитроумные, так что я думаю, что лучше с категорией sendinel.

.
0
ответ дан 13 December 2019 в 19:28
поделиться

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

0
ответ дан 13 December 2019 в 19:28
поделиться

Я не верю, что ни одна из альтернатив не очень хороша.

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

IMO лучшим вариантом является наличие трех таблиц.

Categories
ID
Name

Items
ID
Name

Categories2Items
CategoryID
ItemID

Это устраняет необходимость в NULL (и связанных с ним понятиях), а также позволяет иметь некатегоризированные предметы, а также предметы, принадлежащие нескольким категориям. Этот дизайн также находится в Boyce-Codd нормальной форме, что всегда хорошо ... en.wikipedia.org/wiki/BCNF

0
ответ дан 13 December 2019 в 19:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: