it-swarm-eu.dev

Mnoho až mnoho a slabých entit

Mám entitu, která nemůže existovat, aniž by byla definována jinou, a chci, aby se tato entita účastnila vztahu mezi mnoha lidmi.

Příklad: Interpret má album (album nemůže existovat bez interpreta), album také obsahuje mnoho skladeb, ale stejná skladba může existovat v mnoha albech.

Takže mezi albem a skladbami máme mnoho vztahů.

Pokud je album slabou entitou, pak jeho primární klíč je cizí klíč odkazující na interpreta, takže to nemůže být cizí klíč do jiné tabulky představující vztah mnoho k mnoha.

Otázka zní: je možné mít tento druh vztahu v SQL, a pokud ano, jak to mohu vyjádřit?

16
Raiden Freeman

Myslím, že můžete pomocí diagramu vztahu „diamant“:

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ᵀᴹ

Bohužel nemám dost opakování, abych se vyjádřil k odpověď ypercubeᵀᴹ , takže místo toho pošlu alternativní odpověď - souhlasím s touto odpovědí obecně, ale myslím, že primární klíč a jedinečné protiklady na AlbumTrack jsou nesprávné, protože alba i skladby jsou slabé entity. Například by byla zakázána následující platná data s předepsanými omezeními:

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

Místo toho bych nastavil PRIMARY KEY (artistID, albumID, trackID) a upustil od jedinečného omezení, což by mělo za následek:

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

Skladby jsou stále omezeny na výskyt nejvýše jednou na albu.

Otázka také ve skutečnosti nespecifikuje, že skladby jsou slabé entity (pouze ta alba jsou) - pokud stopy mohou ve skutečnosti existovat nezávisle na umělcích, jsou tabulky Track a AlbumTrack definovány trochu jinak. :

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