传统的方法是使用一个附加的many:many
(联结)表,它链接到两个表:
CREATE TABLE [dbo].[AuthorsBooks] (
-- Optionally, we can give the table its own surrogate PK
[Id] INT IDENTITY(1,1) NOT NULL,
AuthorId INT NOT NULL,
BookId INT NOT NULL,
-- Referential Integrity
FOREIGN KEY(AuthorId) REFERENCES Authors(Id),
FOREIGN KEY(BookId) REFERENCES Books(Id),
-- PK is either the surrogate ...
PRIMARY KEY CLUSTERED ([Id] ASC)
-- ... Or the compound key
-- PRIMARY KEY CLUSTERED (AuthorId, BookId)
);
一个有争议的问题是您是否希望复合键AuthorId, BookId
成为主键,或者是否添加您自己的新代理 - 这通常是一种主观偏好。
要考虑是否为联结表选择复合主键或新代理键的一些要点:
- 如果没有代理项,链接到联结表的外部表将需要存储两个复合键(即需要同时保留
AuthorId
和BookId
作为外键)。
- 所以一个新的代理提供了一个更窄的主键的潜在好处,这意味着任何链接到这个联结表的表都将有一个单一的、更窄的外键。
- 但是,使用复合键,可以有一个优化好处,即表可以直接连接到底层
Books
或Authors
表,而无需先连接到连接表。
下图希望使复合键的情况更清楚(中间表Nationality
是 的联结表PersonCountry
):
编辑
用法很简单——如果链接存在于 many:many 表中,则认为关系存在。要测试是否存在,您可以通过链接表“加入”,例如
-- Find all books written by AuthorId 1234
SELECT b.*
FROM Books b
INNER JOIN AuthorsBooks ab
ON b.Id = ab.BookId
WHERE ab.AuthorId = 1234;