Столбец как первичный ключ или два внешних ключа в качестве первичного ключа

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

введите описание изображения здесь

E-Report имеет один QAP который имеет некоторые Requirement s. QAP и его Requirement s могут использоваться в более чем одном E-Report .

Каждое 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 полями, это сложная конструкция, и есть вероятность ошибки в пропуске одного из ключей.

    Давайте будем гением компьютера.