Molte a molte ed entità deboli


16

Ho un'entità che non può esistere senza essere definita da un'altra e voglio che questa entità partecipi a una relazione molti-a-molti.

Esempio: un artista ha un album (l'album non può esistere senza un artista), l'album ha anche molte tracce, ma la stessa traccia può esistere in molti album.

Quindi abbiamo una relazione molti-a-molti tra l'album e le tracce.

Se l'album è un'entità debole, la sua chiave primaria è una chiave esterna che fa riferimento all'artista, quindi non può essere una chiave esterna per un'altra tabella che rappresenta una relazione molti-a-molti.

La domanda è: è possibile avere questo tipo di relazione in SQL e, in tal caso, come posso esprimerlo?


No, la chiave primaria dell'album sarebbe solo un numero intero che rende l'album unico. Potresti quindi avere una artist_idchiave esterna che fa riferimento all'artista. Se si desidera mappare una singola traccia su più album, utilizzare una tabella di mappatura con track_id, album_id. Facile :)
Philᵀᴹ

Risposte:


16

Penso che tu possa, usando un diagramma di relazione "diamante":

diagramma

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 Avresti senso aggiungere i seguenti vincoli univoci alla tabella AlbumTrack: (trackID, albumID) e (albumID, trackNo)?
AK

@AlexKuznetsov Hai ragione, grazie. "Ridurrò" il PK nel tuo suggerito (albumID, trackNo)e aggiungerò anche l'altro vincolo Unico.
ypercubeᵀᴹ

1
Ricorda di consentire album che non hanno un singolo artista nominale, avendo un artista fittizio chiamato "Varie" o simile o rendendo nulla la colonna artista della tabella degli album. In effetti, potresti avere più di un artista per traccia, quindi potresti aver bisogno di un arrangiamento molti-a-molti anche lì.
David Spillett,

1
@DavidSpillett Sì, potremmo farlo, ma complicherebbe le cose e devia dalla domanda posta. La domanda presuppone / impone che ogni album abbia un singolo artista. Non è possibile avere artisti diversi per traccia, né molti artisti per album o traccia. In effetti, non è un'ottima rappresentazione del mondo reale.
ypercubeᵀᴹ

1
@TimAbell Penso che sia un contrattempo da Workbench in cui sono stati creati i diagrammi (non riconoscendolo lo stesso della connessione Album-AlbumTrack a causa dell'ordine delle colonne nei PK)
ypercubeᵀᴹ

2

Sfortunatamente non ho abbastanza rappresentante per commentare la risposta di ypercubeᵀᴹ , quindi posterò una risposta alternativa - Sono d'accordo con quella risposta in generale, ma penso che la chiave primaria e le contraddizioni uniche AlbumTrack siano errate dato che album e tracce sono entrambi deboli entità. Ad esempio, i seguenti dati validi verrebbero vietati, con i vincoli prescritti:

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

Invece vorrei impostare PRIMARY KEY (artistID, albumID, trackID)e rilasciare il vincolo univoco, risultando in:

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

Le tracce sono ancora obbligate a verificarsi al massimo una volta per album.

Inoltre, la domanda in realtà non specifica che le tracce sono entità deboli (solo che gli album lo sono) - se in realtà le tracce possono esistere indipendentemente dagli artisti, le tabelle Tracke AlbumTracksono definite in modo leggermente diverso:

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)
) ;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.