列为主键或两个外键为主键

时间:2012-06-27 15:40:40

标签: database-design

我有以下数据库设计:

enter image description here

E-Report有一个QAP,其中有一些RequirementQAP及其Requirement可以在多个E-Report中使用。

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

而且,每个Requirement每个Image都会有多个E-ReportEReportReqImg将存储ImageRequirement关系。

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

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

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

您怎么看?

2 个答案:

答案 0 :(得分:1)

  

我的问题是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(例如,EReportReq行具有相同的eReportId,将在物理上“关闭”存储,这可能会对某些查询产生重大影响)
  • 避免代理键上的其他索引。

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

答案 1 :(得分:0)

让我们从这个状态开始:

  

我需要将这两个添加到EReportReqImg

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

要审查的其他选项是结果的简单性SQL,简单比复杂更简单 - 写INNER JOIN,2个字段是复杂的构造,并且可能存在错误的地方错过其中一个键。