Скажем, у меня есть следующая диаграмма ER:
Теперь, если бы я представлял отношение с помощью внешнего ключа School
in Student
, у меня могли бы быть NULL
значения (потому что a Student
не обязательно должен принадлежать a School
), например:
Таким образом, правильный способ (основываясь на том, что я прочитал) - создать таблицу пересечений для представления отношений, например:
Таким образом, никакие NULL
значения не могут присутствовать в таблице School_has_Student
.
Но каковы недостатки использования обнуляемого внешнего ключа вместо создания таблицы пересечений?
Редактировать:
Я по ошибке выбрал ( school_id
, student_id
) в качестве первичного ключа для School_has_Student
таблицы, что сделало отношения многие ко многим. Правильный первичный ключ должен был быть student_id
:
Ответы:
Две модели представляют разные отношения.
Используя таблицу соединений, вы моделируете отношение «многие ко многим».
Используя простой внешний ключ, вы моделируете отношение «один ко многим».
Недостатком обнуляемого внешнего ключа является невозможность смоделировать отношения «многие ко многим», если это то, чего вы пытаетесь достичь.
Основываясь на редактировании вопроса, вы фактически разбиваете таблицу ученика на две таблицы с одинаковым ключом. Я обычно вижу это на таблицах, в которых слишком много полей, поэтому кто-то разбивает их на две части, чтобы было удобнее (я называю это нанесением помады на свинью).
Разбивая таблицу учеников, вы делаете вторую таблицу необязательной, поскольку запись во второй таблице не обязательна. Что очень похоже на поле, которое не нужно устанавливать, потому что оно может быть нулевым.
Если вы хотите, чтобы отношения один-ко-многим, вам было бы лучше использовать одну таблицу и позволить идентификатору школы быть пустым в таблице учеников. Нет причин избегать нулевых значений в полях, даже для внешнего ключа. Это означает, что внешние отношения необязательны: разработчики и администраторы баз данных понимают это ясно, и базовый механизм базы данных, безусловно, должен работать нормально.
Если вы обеспокоены объединениями, не беспокойтесь. Существует четкая семантика того, как объединения работают с пустыми полями. Используя одну таблицу, вы можете объединить две таблицы вместо трех.
источник
NULL
значения?student_id
первичный ключ вSchool_has_Student
таблице, который сохранил отношения как один ко многим. Какие недостатки у этого метода по сравнению с использованием внешнего ключа?Вы написали в комментарии выше:
Когда в столбце внешнего ключа много значений NULL, вашим программам придется иметь дело с этим в основном пустым столбцом для каждой обрабатываемой записи. Столбец, вероятно, будет занимать некоторое дисковое пространство, хотя в 98% всех случаев он пуст, запрос отношения означает запрос этого столбца, который дает вам больше сетевого трафика, и если вы используете ORM, который генерирует ваши классы из ваших таблиц, ваших программ Также потребуется больше места на стороне клиента, чем необходимо. Использование таблицы пересечений позволяет избежать этого, будут необходимы только записи ссылок, если эквивалентный внешний ключ не будет равен NULL в противном случае.
В противоположность этому, если у вас не просто несколько значений NULL, скажем, 50% или более отношений не являются NULL, использование таблицы пересечений дает противоположный эффект - больше дискового пространства, более высокая сложность, приводящая к увеличению сетевого трафика и т. Д.
Таким образом, использование таблицы пересечений является лишь формой оптимизации, приемлемой только для конкретного случая, и особенно в наши дни, когда дисковое пространство и память стали дешевле, а это требуется гораздо реже. Обратите внимание, что «Основы систем баз данных» изначально были написаны более 20 лет назад (я нашел ссылку на второе издание 1994 года), и я полагаю, что рекомендация уже была там в то время. До 1994 года оптимизация пространства была, вероятно, гораздо важнее, чем сегодня, поскольку массовое хранилище было все еще дороже, а компьютеры и сети работали медленнее, чем сегодня.
В качестве дополнительного примечания к отрывочному комментарию: вышеприведенное утверждение просто пытается предвидеть то, что автор «Основы систем баз данных» имел в виду со своей рекомендацией, я думаю, что он делал грубое, общее утверждение, допустимое для большинства систем. В некоторых базах данных есть другие возможные оптимизации, такие как «разреженные столбцы», которые делают использование таблицы пересечений еще более устаревшим.
Так что не поймите эту рекомендацию неправильно. Книга не говорит вам, чтобы вы предпочитали таблицы пересечений для
{0,1}:n
отношений в целом или - как вы писали - что это «правильный путь». Используйте такие оптимизации, которые сделают ваши программы более сложными только тогда, когда они вам действительно нужны.источник
Концептуальная модель будет выглядеть так, что очень неортодоксально, если не сказать так:
Физическая модель будет выглядеть так, что , тем не менее, сбивает с толку (люди будут думать, что это M: M, если они не увидят внимательно):
Мое предложение:
Если у вас есть несколько столбцов (FK или иным образом), которые не относятся к большинству учащихся, разделите таблицы на таблицы ролей с соотношением 1: 1. Но это не потому, что они FK, а потому, что столбцы не применяются к большинству строк.
В противном случае , обнуляемый FK является нормальной частью базы данных и объединения таблиц, как правило , для M: M RELS.
Обычно используются значения 1: 1 для таблиц ролей, имеющих столбцы, которые применяются только в том случае, если объект имеет определенный тип, и извлекающих BLOB-столбцы с целью повышения производительности или хранения. Аводирование нулевых значений в FK не является одним из распространенных случаев для этого.
источник
В дополнение к другим ответам я хотел бы отметить, что нулевое значение для внешнего ключа неоднозначно. Значит ли это:
1) Школа учащегося (если есть) неизвестна (это стандартное значение «ноль» - значение неизвестно)
2) Известно, есть ли у ученика школа, и нет
Если вы используете стандартное значение «ноль», как бы вы представляли «ученик не имеет школы» в своей модели внешнего ключа. В этом случае вам, вероятно, придется создать запись «no school» с собственным идентификатором в школьной таблице. (Не идеально)
источник
NULL
, это может означать: 1) Неизвестное значение. 2) Недоступно или удержано значение. 3) Неприменимый атрибут (я думаю, что эта интерпретация означает, что вы можете указатьNULL
для внешнего ключа).Таблицы базы данных имеют такую замечательную вещь, как ограничения. Таким образом, это очень легко сделать в таблице пересечений, которая позволяет отображать только 1 ученика в таблице, но многие школы в этой таблице. Эффективно давая вам
Теория хороша, но в конце вы будете моделировать свою базу данных после вопросов, которые вы задаете.
Если вы хотите часто задавать вопросы с вопросом: «какие ученики находятся в моей школе», действительно ли вы хотите запросить всю таблицу учеников или иметь простую таблицу пересечений.
В базах данных: оптимизировать под вопросы, которые вы задаете.
источник
Существует случай, когда использование третьей таблицы может иметь смысл. Пример может показаться чисто гипотетическим, но я надеюсь, что он хорошо иллюстрирует мою точку зрения. Предположим, что вы добавили в
students
таблицу больше столбцов, и в какой-то момент вы решили применить уникальность записей с помощью составного индекса для нескольких столбцов. Вполне вероятно, что вам также придется включитьschool_id
колонку, и здесь все становится грязным. Благодаря тому, как был спроектирован SQL, будет возможно вставить несколько одинаковых записей, гдеschool_id
этоNULL
возможно. Это имеет смысл с технической точки зрения, но противоречит здравому смыслу и может привести к неожиданным результатам. С другой стороны, обеспечить уникальность таблицы пересечения легко.Недавно мне пришлось смоделировать такое «необязательное» отношение, где требование ограничения уникальности было связано со столбцом метки времени. Оставление в таблице пустого внешнего ключа внезапно приведет к возможности вставки записей с одинаковой отметкой времени (предположим, это запись по умолчанию, установленная для записей, которые еще не были проверены / одобрены) - и единственным выходом было удаление обнуляемый столбец.
Итак, как вы можете видеть, это довольно специфический случай, и, как отмечали другие, в большинстве случаев вы будете в порядке со всеми
NULL
значениями. Это действительно зависит от конкретных требований вашей модели.источник
В дополнение ко многим хорошим предложениям, которые я уже представил, лично я не фанат внешних ключей, если они действительно не нужны. Во-первых, это отношение M: M, на которое вы ссылаетесь. Кроме того, вызов внешнего ключа и, следовательно, включение этих данных таблицы в ваши запросы, повышает сложность и, в зависимости от размера таблицы, снижает производительность. Как уже говорили другие, пустые поля FK могут не поддерживаться и могут создавать проблемы целостности данных.
Если вы определяете штат, в котором школа ученика неизвестна или пуста, NULL не будет дифференцировать эти условия. (снова мы возвращаемся к целостности данных.) Предложение таблицы ролей от Tulains элегантно и допускает чистые нулевые значения.
источник