【问题标题】:A column as primary key or two foreign keys as primary key一列作为主键或两个外键作为主键
【发布时间】:2012-06-29 02:42:04
【问题描述】:

我有以下数据库设计:

一个E-Report 有一个QAP,其中有一些Requirements。一个QAP 及其Requirements 可以用于多个E-Report

每个Requirement 都会在每个电子报告中确认是/否。我添加了EReportReq 来存储需求确认值(用户将设置这些值)。

而且,每个Requirement 在每个E-Report 上都会有多个ImageEReportReqImg 将存储 ImageRequirement 关系。

如果您需要有关此数据库模型的更多详细信息,请告诉我。

我的问题是关于EReportReq 表。我不确定是否需要将列作为主键 (EReportReqId),或者我可以使用 eReportIdrequirementId 作为主键。

如果我使用eReportIdrequirementId这两列作为主键,我需要将这两列添加到EReportReqImg表中,所以我不知道这种方法是否比我的更好。

你怎么看?

【问题讨论】:

    标签: database-design


    【解决方案1】:

    让我们从这个状态开始:

    我需要将这两个添加到 EReportReqImg

    通常使用 2 FK 作为 PK 是不可更改数据的正常做法。因此,如果EReportReq 不应该以将其拖动到另一个requirementIdeReportId 的方式进行更改,则使用复合键。否则,使用单值主键更加健壮和高效 - 因为它在此期间不会更改,因此您不需要编写触发器或使用棘手的级联来更新子表。

    要查看的其他选项是结果 SQL 的简单性,简单胜于复杂 - 使用 2 个字段编写 INNER JOIN 是复杂的构造,并且可能会错过其中一个键的错误位置。

    【讨论】:

      【解决方案2】:

      我的问题是关于EReportReq 表。我不确定是否需要将列作为主键 (EReportReqId),或者我可以使用 eReportIdrequirementId 作为主键。

      您可以使用它们中的任何一个 - 它们都不是绝对“更好”的。请注意,如果您决定使用第一种方法,还要在 {eReportId, requirementId} 上创建一个 UNIQUE 约束。

      第一种方法(使用非识别关系和代理键)导致:

      • 子表中的“精简”外键(在本例中为 EReportReqImg) - 正如您已经指出的那样,
      • 级联 ON UPDATE 不会传播到子级(因此,如果您更新 EReport.eReportId,则只有 EReportReq.eReportId 是级联更新的,而不是 EReportReqImg.eReportId
      • 并且可以对 ORM 更加友好。

      另一方面,第二种方法(识别关系和自然键):

      • 对 JOIN 的需求可能更少(例如,您不需要 EReportReqImg JOIN EReportReq 只是为了找出 requirementId - 您可以直接在 EReportReqImg.requirementId 中找到它),
      • 更适合clustered tables(例如,具有相同eReportIdEReportReq 行将在物理上“关闭”存储,这可能对某些查询有很大好处)
      • 避免代理键上的附加索引。

      由于您有少量子表,“胖”FK 并不重要,而且由于我们处理的是 ID,它们不太可能更改,并且级联 ON UPDATE 不太可能成为问题。所以,我的直觉是采用第二种方法,但您可能还有其他一些考虑因素可能会使您的决定朝着不同的方向倾斜...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-06
        • 1970-01-01
        • 2020-10-15
        • 2012-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多