J'ai une entité qui ne peut exister sans être définie par une autre, et je veux que cette entité participe à une relation plusieurs-à-plusieurs.
Exemple: un artiste a un album (l'album ne peut pas exister sans artiste), l'album contient également de nombreuses pistes, mais la même piste peut exister dans de nombreux albums.
Nous avons donc une relation plusieurs à plusieurs entre l'album et les morceaux.
Si l'album est une entité faible, sa clé primaire est une clé étrangère référençant l'artiste, il ne peut donc pas être une clé étrangère vers une autre table représentant une relation plusieurs-à-plusieurs.
La question est: est-il possible d'avoir ce type de relation en SQL, et si oui, comment l'exprimer?
Je pense que vous pouvez, en utilisant un diagramme de relation "diamant":
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
) ;
Malheureusement, je n'ai pas assez de représentants pour commenter réponse de ypercubeᵀᴹ , donc je posterai une autre réponse à la place - je suis d'accord avec cette réponse en général, mais je pense que la clé primaire et les contraintes uniques sur AlbumTrack
sont incorrects étant donné que les albums et les pistes sont des entités faibles. Par exemple, les données valides suivantes seraient, avec les contraintes prescrites, interdites:
artistID | albumID | trackID | trackNo
----------+---------+---------+---------
1 | 1 | 1 | 1
2 | 1 | 1 | 1
Au lieu de cela, je définirais PRIMARY KEY (artistID, albumID, trackID)
et supprimerais la contrainte unique, résultant en:
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)
) ;
Les morceaux sont toujours contraints de se produire au plus une fois par album.
De plus, la question ne spécifie pas réellement que les pistes sont des entités faibles (seulement que les albums le sont) - si les pistes peuvent en fait exister indépendamment des artistes, les tables Track
et AlbumTrack
sont définies légèrement différemment :
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)
) ;