复合主键与否?

san*_*one 18 database-design composite-primary-key

这让我很困惑.我经常在数据库表中使用复合主键.这种方法的不好的一面是,当我删除或编辑条目时,我还有额外的工作.但是,我觉得这种方法符合数据库设计的精神.

另一方面,有我的朋友,他们从不使用复合键,而是在表中引入另一个"id"列,而所有其他键只是FK.在编写删除和编辑过程时,它们的工作量要少得多.但是,我不知道它们如何保留数据条目的唯一性.

例如:
方式1

create table ProxUsingDept (
    fkProx int references Prox(ProxID) NOT NULL,    
    fkDept int references Department(DeptID) NOT NULL,    
    Value int,    
    PRIMARY KEY(fkProx,fkDept)
)
Run Code Online (Sandbox Code Playgroud)

方式2

create table ProxUsingDept (
        ID int NOT NULL IDENTITY PRIMARY KEY
        fkProx int references Prox(ProxID) NOT NULL,    
        fkDept int references Department(DeptID) NOT NULL,    
        Value int
)
Run Code Online (Sandbox Code Playgroud)

哪种方式更好?使用第二种方法有什么不好的方面?有什么建议?

mar*_*c_s 26

我个人更喜欢你的第二种方法(并且几乎100%都会使用它) - 介绍一个代理ID字段.

为什么?

  • 使引用表的表更容易生活 - 只需一个ID列(而不是2,3,甚至更多列,您需要一直加入),JOIN条件更简单

  • 使生活变得更容易,因为任何引用表的表只需要携带一个ID外键字段 - 而不是复合键中的几列

  • 因为数据库可以处理唯一ID列的创建(使用INT IDENTITY),所以生活变得更加容易

但是,我不知道它们如何保留数据条目的唯一性.

非常简单:在复合列上放置一个UNIQUE INDEX,否则您将用作主键!

CREATE UNIQUE INDEX UIX_WhateverNameYouWant 
   ON dbo.ProxUsingDept(fkProx, fkDept)
Run Code Online (Sandbox Code Playgroud)

现在,你的表保证你的表中永远不会有一对重复(fkProx, fkDept)- 问题解决了!

  • @PerformanceDBA:我不同意你的陈述 - 我将**总是**更喜欢一个简单的INT代理键而不是一个复杂的,"自然的"复合键,因为我提到的确切原因 - 易用性和易于创建外键关系.我已经看过很多次人们只是放弃了创建FK约束,因为他们的PK是6,10或甚至更多列的复合怪物.... (8认同)
  • @PerformanceDBA:感谢您尊重您个人意见.你可以放心,任何阅读此内容的人都会给予它应有的全部考虑. (6认同)
  • @askmo.所以让我做对了.为了简化编码,你会添加(a)一个自动增量列(b)和附加索引?不关心完整的非数据或非业务需求?没有担心负面表现?丢失的导航(见拉里的回答)? (4认同)
  • @marc_s.当你让那些关心自己喜欢和不喜欢的人时会发生这种情况; 他们易于编码,设计"数据库".而不是关注整体使用,性能,标准,关系力量的专业数据库设计师.该行业处于非常悲惨的状态. (4认同)
  • (续)自然键 - *特别是*自然复合键 - 使桌子更脆.这是事实.*每种*约束方式都会使表格变得更脆弱,但是自然复合键会更加复杂,因为您将技术约束(PK)与业务约束(用户指定的唯一性)结合起来.要求可以*和做*改变,我怀疑你已经处于不止一种情况,其中自然复合键突然变成不再适合作为主键的东西.说"真正的"DBA是关注整体使用的(或者更确切地说是那些)是不诚实的 (3认同)
  • @亚当.这完全是完全错误的,这是一个可以很容易证明的事实.业界的一部分问题是人们发表意见**作为事实**.技术事实与意见不同,它们不随人或其资格水平而变化.如果您真的相信任何这些"事实",请打开一个新问题,我会接受您的每一点.但是,评论中这种冗长的个人观点是让你的"事实"跨越的奇怪方式.在那之前,他们只是个人意见,没有证据,受到挑战. (3认同)
  • @PerformanceDBA:虽然我不确定你为什么这么苛刻,但你们都有有效的观点.像许多公约一样,这通常归结为个人偏好.是的,在某些情况下,自然密钥(复合或非复合)将提供性能或存储益处.然而,数据库设计 - 如应用程序设计,通信协议设计等 - 无法在真空中查看.设计的一致性(例如,始终使用自然密钥或代理密钥)**通常会提供一个好处,即使该优势在另一层. (2认同)
  • (续)他们只是***).用户不会详细说明您在数据库中定义的标识符.如果您通过改变猫毛的折射率来存储数据,则用户不会(或不应该)关心.用户关心放入的数据是否正确且快速地发出. (2认同)

Lar*_*tig 17

你问以下问题:

但是,我不知道它们如何保留数据条目的唯一性.

可以通过在列上声明单独的复合UNIQUE索引来保留唯一性,否则这些索引将形成自然主键.

哪种方式更好?

不同的人有不同的意见,有时坚持不懈.我想你会发现更多人使用代理整数键(而不是那使它成为"正确"的解决方案).

使用第二种方法有什么不好的方面?

以下是使用代理键的一些缺点:

  1. 您需要一个额外的索引来维护自然主键的唯一性.

  2. 在选择数据以获取所需结果时,有时需要额外的JOIN(当您只使用复合自然键中的列满足查询要求时会发生这种情况;在这种情况下,您可以使用外键列而不是JOINing回到原来的表).