Столбец как первичный ключ или два внешних ключа в качестве первичного ключа
У меня есть следующий дизайн базы данных:
E-Report
имеет один QAP
который имеет некоторые Requirement
s. QAP
и его Requirement
s могут использоваться в более чем одном E-Report
.
- Как хранить исторические данные
- Дизайн базы данных - статьи, сообщения в блогах, фотографии, истории
- Что означает основной конец ассоциации в соотношении 1: 1 в структуре Entity
- Неверный внешний ключ плохой практики?
- Firebase: настройка дополнительных пользовательских свойств
Каждое Requirement
будет иметь подтверждение Да / Нет в каждом E-отчете. Я добавил EReportReq
для хранения значений подтверждений требований (пользователи установят эти значения).
Кроме того, каждое Requirement
будет иметь более одного Image
на каждом E-Report
. EReportReqImg
будет хранить отношения Image
и Requirement
.
Если вам нужна дополнительная информация об этой модели базы данных, скажите, пожалуйста.
Мой вопрос о таблице EReportReq
. Я не уверен, нужен ли мне столбец в качестве первичного ключа ( EReportReqId
), или я могу использовать eReportId
и eReportId
качестве первичного ключа.
Если я использую эти два столбца, eReportId
и eReportId
как первичный ключ, мне нужно будет добавить эти два в таблицу EReportReqImg
, поэтому я не знаю, лучше ли этот подход, чем мой.
Как вы думаете?
Мой вопрос о таблице
EReportReq
. Я не уверен, нужен ли мне столбец в качестве первичного ключа (EReportReqId
), или я могу использоватьeReportId
иeReportId
качестве первичного ключа.
Вы можете использовать любой из них – ни один из них не является абсолютно «лучшим». Просто будьте осторожны, если вы решите использовать первый подход, также создайте ограничение UNIQUE на {eReportId, requirementId}
.
Первый подход (с неидентифицирующими отношениями и суррогатным ключом) приводит к:
- «более компактные» foreign keys в дочерних таблицах (это
EReportReqImg
в этом случае) – как вы уже отметили, - каскадное включение UPDATE не распространяется на детей (поэтому, если вы обновляете
EReport.eReportId
,EReportReq.eReportId
толькоEReportReq.eReportId
, но неEReportReqImg.eReportId
) - и может быть более дружелюбным к ORM.
С другой стороны, второй подход (с идентификацией отношений и естественными ключами):
- имеет потенциально меньшую потребность в JOINs (например, вам не нужно
EReportReqImg JOIN EReportReq
только для выясненияrequirementId
– у вас есть это прямо вEReportReqImg.requirementId
), - лучше подходит для кластеризованных таблиц (например, строки
EReportReq
с одним и тем жеeReportId
будут физически «закрываться», что может значительно помочь некоторым запросам) - избегает дополнительного индекса суррогатного ключа.
Поскольку у вас небольшое количество дочерних таблиц, «толстые» FK не имеют большого значения, и поскольку мы имеем дело с идентификаторами, они вряд ли будут меняться, и каскадирование ON UPDATE вряд ли будет проблемой. Итак, мой инстинкт состоит в том, чтобы пойти со вторым подходом, но у вас могут быть и другие соображения, которые могут опрокинуть ваше решение в другом направлении …
Начнем с этого состояния:
Мне нужно будет добавить эти два в EReportReqImg
В общем случае использование 2 FK в качестве ПК является обычной практикой для неизменяемых данных. Поэтому, если EReportReq
не должен быть изменен так, что вы перетащите его в другое requirementId
или eReportId
тогда используйте составной ключ. В противном случае более безопасно и эффективно использовать однозначный первичный ключ – поскольку он не изменяется в течение времени, и в результате вам не нужен триггер записи или использование сложного каскада для обновления дочерних таблиц.
Другим вариантом для обзора является простота результата SQL, просто лучше, чем сложная – напишите INNER JOIN
с 2 полями, это сложная конструкция, и есть вероятность ошибки в пропуске одного из ключей.