web-dev-qa-db-ja.com

多対多および弱いエンティティ

別のエンティティに定義されていないと存在できないエンティティがあり、このエンティティに多対多の関係に参加してもらいたい。

例:アーティストはアルバムを持っています(アルバムはアーティストなしでは存在できません)、アルバムにも多くのトラックがありますが、同じトラックが多くのアルバムに存在できます。

つまり、アルバムとトラックの間には多対多の関係があります。

アルバムが弱いエンティティである場合、その主キーはアーティストを参照する外部キーであるため、多対多の関係を表す別のテーブルへの外部キーにすることはできません。

問題は、SQLでこの種の関係を持つことは可能ですか?その場合、どのようにそれを表現するのですか?

16
Raiden Freeman

「ダイヤモンド」関係図を使用して、できると思います。

diagram

CREATE TABLE Artist
( artistID INT NOT NULL
, name VARCHAR(100) NOT NULL
, PRIMARY KEY (artistID)
) ;

CREATE TABLE Album
( artistID INT NOT NULL
, albumID INT NOT NULL
, title VARCHAR(100) NOT NULL
, PRIMARY KEY (artistID, albumID)
, FOREIGN KEY (artistID)
    REFERENCES Artist (artistID)
) ;

CREATE TABLE Track
( artistID INT NOT NULL
, trackID INT NOT NULL
, title VARCHAR(100) NOT NULL
, PRIMARY KEY (artistID, trackID)
, FOREIGN KEY (artistID)
    REFERENCES Artist (artistID)
) ;

CREATE TABLE AlbumTrack
( artistID INT NOT NULL
, albumID INT NOT NULL
, trackID INT NOT NULL
, trackNo INT NOT NULL
, PRIMARY KEY (albumID, trackNo)
, FOREIGN KEY (artistID, albumID)
    REFERENCES Album (artistID, albumID)
, FOREIGN KEY (artistID, trackID)
    REFERENCES Track (artistID, trackID)
, UNIQUE (trackID, albumID)               -- this Unique constraint should be added
                                          -- if no track is allowed twice in an album
) ;
16
ypercubeᵀᴹ

残念ながら、私は ypercubeᵀᴹの回答 にコメントするのに十分な担当者がいないため、代わりの回答を投稿します-一般的にはその回答に同意しますが、AlbumTrackは正しくありません。たとえば、次の有効なデータは、規定の制約がある場合、許可されません。

_ artistID | albumID | trackID | trackNo 
----------+---------+---------+---------
        1 |       1 |       1 |       1
        2 |       1 |       1 |       1
_

代わりに、PRIMARY KEY (artistID, albumID, trackID)を設定して一意の制約を削除し、その結果は次のようになります。

_CREATE TABLE Artist
( artistID INT NOT NULL
, name VARCHAR(100) NOT NULL
, PRIMARY KEY (artistID)
) ;

CREATE TABLE Album
( artistID INT NOT NULL
, albumID INT NOT NULL
, title VARCHAR(100) NOT NULL
, PRIMARY KEY (artistID, albumID)
, FOREIGN KEY (artistID)
    REFERENCES Artist (artistID)
) ;

CREATE TABLE Track
( artistID INT NOT NULL
, trackID INT NOT NULL
, title VARCHAR(100) NOT NULL
, PRIMARY KEY (artistID, trackID)
, FOREIGN KEY (artistID)
    REFERENCES Artist (artistID)
) ;

CREATE TABLE AlbumTrack
( artistID INT NOT NULL
, albumID INT NOT NULL
, trackID INT NOT NULL
, trackNo INT NOT NULL
, PRIMARY KEY (artistID, albumID, trackID)
, FOREIGN KEY (artistID, albumID)
    REFERENCES Album (artistID, albumID)
, FOREIGN KEY (artistID, trackID)
    REFERENCES Track (artistID, trackID)
) ;
_

トラックは、アルバムごとに最大1回発生するように制限されています。

また、質問は実際にはトラックが弱いエンティティであることを指定していません(アルバムのみがそうです)-トラックがアーティストとは関係なく実際に存在できる場合、TrackおよびAlbumTrackテーブルはわずかに異なって定義されます:

_CREATE TABLE Track
( trackID INT NOT NULL
, artistID INT
, title VARCHAR(100) NOT NULL
, PRIMARY KEY trackID
, FOREIGN KEY (artistID)
    REFERENCES Artist (artistID)
) ;

CREATE TABLE AlbumTrack
( artistID INT NOT NULL
, albumID INT NOT NULL
, trackID INT NOT NULL
, trackNo INT NOT NULL
, PRIMARY KEY (artistID, albumID, trackID)
, FOREIGN KEY (artistID, albumID)
    REFERENCES Album (artistID, albumID)
, FOREIGN KEY (trackID)
    REFERENCES Track (trackID)
) ;
_
2
Gord Stephen