在联结表中,我应该使用主键和唯一约束,还是复合/复合键?

use*_*679 5 t-sql sql-server compound-key

我已经阅读了一些似乎使这个重复的问题的内容.但阅读所有这些让我不确定.我希望得到一个基于下面绝对例子的答案,因为许多问题/答案会来回讨论.

如果我有:

dbo.Book
--------
BookID PK int identity(1,1)

dbo.Author
----------
AuthorID PK int identity(1,1)
Run Code Online (Sandbox Code Playgroud)

现在我有一个简单的联结表的两个选择:

dbo.BookAuthor
--------------
BookID CPK and FK
AuthorID CPK and FK
Run Code Online (Sandbox Code Playgroud)

以上将是两个FK上的复合/复合键,以及为两列设置FK关系 - 也可以在删除时使用Cascade.

要么

dbo.BookAuthor
--------------
RecordID PK int identity(1,1)
BookID FK
AuthorID FK
Run Code Online (Sandbox Code Playgroud)

BookID和AuthorID上的外键关系,以及删除时的Cascade.还在BookID和AuthorID上设置唯一约束.

我正在寻找一个简单的答案,为什么一个方法比ABOVE特定例子中的另一个更好.我正在阅读的答案非常详细,我正准备解决一个复合键,但后来观看了一个视频,其中示例使用了像我的第一个示例中的Identity列.

似乎这个主题略微被撕成两半,但我的直觉告诉我,我应该只使用复合键.

什么更有效的查询?它似乎有一个PK标识列,同时在两列上设置了一个唯一的约束,即使有一点,FK关系也会更加昂贵.

Joe*_*orn 10

这是我在大学期间从数据库课程中一直记得的东西.我们正在讨论关于"实体设计"的教科书中的部分,它正在谈论连接表......我们将它们称为交叉表或交叉关系.这位教授说,根据他的经验,多对多联合表几乎总是表明一个未被识别的缺失实体.这些实体几乎总是以自己的数据结束.

我们得到了一个学生和课程实体的例子.对于学生参加课程,您需要在这两者之间建立联系.你实际拥有的是一个新实体:一个注册.在这种情况下,附加数据将是信用类型(审计与常规)或最终等级.

我记得今天的建议......但我并不总是遵循它.在这种情况下我要做的就是停止,并确保回到问题的利益相关者,并与他们一起处理我们在这个联结中可能仍然缺少的数据点.如果我们真的找不到任何东西,那么我将使用复合键.当我们找到数据时,我们会想到一个更好的名称,它会得到一个代理键.


Fel*_*tan 6

我更喜欢第一种设计,使用复合键。即使父表有标识列,联结表上的标识列也不会给您带来优势。您不会BookAuthor使用标识列查询 ,而是使用BookIDand查询它AuthorID

此外,增加的身份将允许重复的BookID-AuthorID组合,除非你把一个约束。

此外,如果您的主键是(BookID, AuthorID),则需要在 上建立索引AuthorID, BookID)。如果您想查询作者所写的书籍,这将有所帮助。


Pie*_*ens 6

作为代理键的好处的坚定支持者和传播者,我仍然对全键连接表(例如您的第一个示例)进行了例外处理。代理键的好处之一是引擎通常针对连接单个整数字段进行了优化,这是默认和最常见的情况。

你的第一个提议仍然获得了这个好处,但在每个索引级别上的扇形放置也增加了 50%,减少了连接表上索引的整体大小和高度。尽管对于比大型表更小的任何东西来说,这样做的性能优势可能可以忽略不计,但它是最佳实践,而且是免费的。

当我可能选择其他设计时,关系是否会产生额外的列。那时它不再是严格的连接表。


MWi*_*mse 5

使用复合键也是我的选择。原因如下:

更少的存储开销

假设您将使用代理键。由于您可能想要查询特定书籍的所有作者,反之亦然,因此您需要以 BookId 和 AuthorId 开头的索引。出于性能原因,您应该在两个索引中都包含另一列以防止聚集键查找。您可能希望将其中一个设为唯一,以确保没有重复的 BookId/AuthorId 组合添加到表中。

所以作为一个最终结果:

  • 数据存储3次而不是2次
  • 要验证 2 个唯一约束而不是 1 个

查询联结表引用表

即使您要添加一个表,例如Contributions (AuthorId, BookId, ...)引用连接表。大多数查询根本不需要触及联结表。例如:查找特定作者的所有贡献只涉及作者和贡献表。