Plusieurs à plusieurs et entités faibles


16

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?


Non, la clé primaire de l'album ne serait qu'un entier qui rend l'album unique. Vous pouvez alors avoir une artist_idclé étrangère qui fait référence à l'artiste. Si vous souhaitez qu'une seule piste soit mappée sur plusieurs albums, utilisez une table de mappage avec track_id, album_id. Facile :)
Philᵀᴹ

Réponses:


16

Je pense que vous pouvez, en utilisant un diagramme de relation "diamant":

diagramme

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
) ;

1
+1 Serait-il judicieux d'ajouter les contraintes uniques suivantes au tableau AlbumTrack: (trackID, albumID) et (albumID, trackNo)?
AK

@AlexKuznetsov Vous avez raison, thnx. Je vais "réduire" le PK à votre suggestion (albumID, trackNo)et ajouter également l'autre contrainte Unique.
ypercubeᵀᴹ

1
N'oubliez pas d'autoriser les albums qui n'ont pas d'artiste nominal unique, soit en ayant un artiste factice appelé "Divers" ou similaire, soit en rendant la colonne artiste de la table des albums nulle. En fait, vous pourriez avoir plus d'un artiste par piste, vous pourriez donc également avoir besoin d'un arrangement plusieurs-à-plusieurs.
David Spillett

1
@DavidSpillett Oui, nous pourrions le faire mais cela compliquerait les choses et dévierait la question posée. La question suppose / dicte que chaque album a un seul artiste. Impossible d'avoir différents artistes par piste, ni beaucoup d'artistes par album ou piste. Ce n'est pas une très bonne représentation du monde réel, en effet.
ypercubeᵀᴹ

1
@TimAbell Je pense que c'est un incident de Workbench où les diagrammes ont été créés (ne le reconnaissant pas de la même manière que la connexion Album-AlbumTrack en raison de l'ordre des colonnes dans les PK)
ypercubeᵀᴹ

2

Malheureusement, je n'ai pas assez de représentant pour commenter la réponse de ypercubeᵀᴹ , donc je posterai une réponse alternative à 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 AlbumTrack sont incorrectes étant donné que les albums et les pistes sont tous deux faibles entités. 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, ce qui entraînerait:

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 tableaux Tracket AlbumTracksont définis 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)
) ;
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.