复合主键与附加"ID"列?

use*_*112 46 sql database sql-server database-design

如果我们有这样一个表:

书籍(假装"ISBN"不存在)

  • 作者
  • 标题
  • 出版年份
  • 价钱

有人可能会说{Author,Title,Edition}可能是候选/主键.

是什么决定候选/主键应该是{Author,Title,Edition}还是应该使用ID列,{Author,Title,Edition}是唯一的索引/键约束?

也是

  • 作者(PK)
  • 标题(PK)
  • 版(PK)
  • 出版年份
  • 价钱

更好,或:

  • ID(PK)
  • 作者
  • 标题
  • 出版年份
  • 价钱

其中{Author,Title,Edition}是一个额外的唯一索引/约束?

Dam*_*vic 45

假设{Author,Title,Edition}唯一标识一本书,则以下内容成立:

  1. 它是一个(超级)键 - 唯一标识元组(行).

  2. 它是不可简化的 - 删除任何列都不会使它成为关键.

  3. 它是候选键 - 不可缩减的键是候选键.

现在让我们考虑ID(整数)

我可以推断,Book表键将在少数其他表中显示为外键,也可以在少数索引中显示.因此,它将占用相当多的空间 - 比如三列×40个字符(或者其他......) - 在每个表中以及匹配的索引中.

为了使这些"其他"表和索引更小,我可以向表中添加一个唯一整数列,Book以用作将作为外键引用的键.说出类似的话:

alter table `Book` add `BookID` integer not null identity;
Run Code Online (Sandbox Code Playgroud)

由于BookID(必须)是唯一的,该表现在Book有两个候选键.

现在我可以选择BookID作为主键.

alter table Book add constraint pk_Book primary key (BookID);
Run Code Online (Sandbox Code Playgroud)

但是,{Author,Title,Edition} 必须保留一个键(唯一)以防止这样的事情:

BookID  Author      Title           Edition
----------------------------------------------- 
  1      C.J.Date  Database Design     1
  2      C.J.Date  Database Design     1
Run Code Online (Sandbox Code Playgroud)

总结一下,添加BookID- 并选择它作为主要 - 并没有停止 {Author,Title,Edition}成为(候选)键.它仍然必须有自己唯一的约束,通常是匹配的索引.

还要注意,从设计角度来看,这个决定是在"物理层面"完成的.通常,在设计的逻辑层面上,这ID不存在 - 它是在考虑列大小和索引时引入的.因此物理模式源于逻辑模式.根据数据库大小,RDBMS和使用的硬件,这些大小推理都不会产生可测量的影响 - 所以使用{Author,Title,Edition}PK作为一个非常好的设计 - 直到证明不同.


Gil*_*anc 16

通常,您不希望主键更改值.这就是使用盲或替代主键的原因.

假设您使用Author作为主键的一部分创建了Book表.

假设你在大约一年后发现你拼错了"Ray Bradbury".或者更糟糕的是,你拼错了"Rachael Bloom".想象一下,您需要修改多少个数据库行来纠正拼写错误.想象一下,必须更改多少个索引引用.

但是,如果您有一个带有代理键的Author表,则只需更正一行.不需要更改索引.

最后,数据库表名通常是单数(Book),而不是复数(Books).

  • 不同意关于单数与复数(表格包含一组内容(例如"书籍"),即使该集只是一行).但这是一个完全不同的主观论点,并不属于恕我直言. (11认同)
  • 我同意吉尔伯特的观点.我几乎总是添加某种行标识符(通常是一个int标识列),即使看起来有其他东西可能是关键.看看这个 - 更容易更新用户,其中username ='jr33s22dt6uwwdrrws33ww'或更新用户userid = 4 (3认同)

小智 7

使用代理主键方案的另一个好理由是,如果未来唯一性约束应该更改(例如,需要添加ISBN以使书籍唯一).重新输入数据会更容易.