従来の方法は、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)
);
重要な点の1つは、複合キー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;