复合vs代理主键

时间:2014-08-14 03:48:30

标签: sql-server database-design

我正在设计一个具有以下要求的数据库:

  • 组织可以独立存在
  • 组织可以包含任意数量的不同条款(日期范围)
  • 组织可以有任意数量的调查类型(学生,教师,家长等)
  • 调查表格分配了术语和调查类型

这种结构可能是:

组织

 - OrganizationId INT IDENTITY(1,1) NOT NULL PRIMARY KEY

期限

 - TermId INT IDENTITY(1,1) NOT NULL PRIMARY KEY
 - OrganizationId INT NOT NULL REFERENCES Organization(OrganizationId)

SurveyType

 - SurveyTypeId IDENTITY(1,1) NOT NULL PRIMARY KEY
 - OrganizationId INT NOT NULL REFERENCES Organization(OrganizationId)

SurveyForm

 - SurveyFormId INT IDENTITY(1,1) NOT NULL PRIMARY KEY
 - SurveyTypeId INT NOT NULL REFERENCES SurveyType(SurveyTypeId)
 - TermId INT NOT NULL REFERENCES Term(TermId)

该结构与单个代理主键的流行强调保持一致。但是,该结构会牺牲数据完整性,因为SurveyForm记录很容易从TermIdSurveyTypeId获得OrganizationOrganizationId

为了解决数据完整性问题,您似乎必须添加(OrganizationId, SurveyTypeId)并在复合键(OrganizationId, TermId)和{{1}}中使用它。在这个例子中,这是可以容忍的,但随着模式变得更加完整,复合密钥大小会增加。

所以我的问题是,人们现在通常如何处理这个问题(大多数在线参考是从2008年开始,当时我认为可能存在不同的数据库设计问题)?作为必然结果,何时可以将外键添加到表中以减少为常用表达式连接的表的数量?

2 个答案:

答案 0 :(得分:0)

我认为可以采用一种方法来避免循环引用,首先是通过定义谁真正依赖于谁以及删除多余的依赖项。

问题是...... Organization是否允许Term随机关联到Survey,而不关心任何Organization关联?我想知道Term是否真的需要直接或间接地通过SurveyOrganization相关联。例如,如果Term无法与Organization的{​​{1}}无关联的Survey关联,那么组织 - 期限关系就没用了,如果它反之亦然,那么不需要Organization-SurveyType

答案 1 :(得分:0)

从学术上讲,您可以沿着两个谱系迁移组织密钥。毕竟,这只是4个字节:

create table dbo.Organization (
    OrganizationId INT IDENTITY(1,1) PRIMARY KEY
);
go

create table dbo.Term (
    TermId INT IDENTITY(1,1) NOT NULL,
    OrganizationId INT NOT NULL REFERENCES dbo.Organization(OrganizationId),
    primary key (OrganizationId, TermId)
);
go

create table dbo.SurveyType (
    SurveyTypeId int IDENTITY(1,1) NOT NULL,
    OrganizationId INT NOT NULL REFERENCES dbo.Organization(OrganizationId),
    primary key (OrganizationId, SurveyTypeId)
);
go

create table dbo.SurveyForm (
    SurveyFormId INT IDENTITY(1,1) NOT NULL,
    OrganizationId int not null,
    SurveyTypeId INT NOT NULL,
    TermId INT NOT NULL,
    primary key (OrganizationId, SurveyTypeId, TermId),
    foreign key (OrganizationId, TermId) references dbo.Term (OrganizationId, TermId),
    foreign key (OrganizationId, SurveyTypeId) references dbo.SurveyType (OrganizationId, SurveyTypeId)
);
go

这些表肯定违反了一些NF,我不记得哪一个,但我确定你可以自己处理它。

虽然这种设计方法几乎可以被视为仓库的必需品(特别是如果您汇总来自不同来源的数据),我绝不会推荐它用于任何真实的OLTP。更简单的解决方案是:

  • 通过存储过程执行所有修改,这将对这种可能的差异进行适当的检查。
  • 确保没有用户有权在dbo.SurveyForm中直接添加/修改数据,从而绕过上述SP中实施的业务规则。