Viele zu vielen und schwache Wesen


16

Ich habe eine Entität, die nicht existieren kann, ohne von einer anderen definiert zu werden, und ich möchte, dass diese Entität an einer Viele-zu-Viele-Beziehung teilnimmt.

Beispiel: Ein Künstler hat ein Album (das Album kann nicht ohne einen Künstler existieren), das Album hat auch viele Titel, aber der gleiche Titel kann in vielen Alben existieren.

Wir haben also eine Beziehung zwischen dem Album und den Tracks.

Wenn das Album eine schwache Entität ist, ist sein Primärschlüssel ein Fremdschlüssel, der auf den Interpreten verweist. Daher kann es kein Fremdschlüssel für eine andere Tabelle sein, die eine Viele-zu-Viele-Beziehung darstellt.

Die Frage ist: Ist es möglich, eine solche Beziehung in SQL zu haben, und wenn ja, wie drücke ich sie aus?


Nein, der Primärschlüssel des Albums wäre nur eine Ganzzahl, die das Album einzigartig macht. Möglicherweise haben Sie dann einen artist_idFremdschlüssel, der auf den Künstler verweist. Wenn Sie möchten, dass ein einzelner Titel mehreren Alben zugeordnet wird, verwenden Sie eine Zuordnungstabelle mit track_id, album_id. Easy :)
Philᵀᴹ

Antworten:


16

Ich denke, Sie können mit einem "Diamant" -Beziehungsdiagramm:

Diagramm

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 Wäre es für Sie sinnvoll, der AlbumTrack-Tabelle die folgenden eindeutigen Einschränkungen hinzuzufügen: (trackID, albumID) und (albumID, trackNo)?
AK

@AlexKuznetsov Du hast recht, danke. Ich werde die PK auf Ihren Vorschlag "verkleinern" (albumID, trackNo)und auch die andere Unique-Einschränkung hinzufügen.
Ypercubeᵀᴹ

1
Denken Sie daran, Alben zuzulassen, die keinen einzigen nominalen Interpreten haben, indem Sie entweder einen Dummy-Interpreten namens "Various" oder einen ähnlichen Interpreten haben oder indem Sie die Interpretenspalte der Albumtabelle auf null setzen. Tatsächlich könnten Sie mehr als einen Interpreten pro Track haben, sodass Sie dort möglicherweise auch ein Many-to-Many-Arrangement benötigen.
David Spillett

1
@ DavidSpillett Ja, wir könnten das tun, aber es würde die Dinge komplizieren und von der gestellten Frage abweichen. Die Frage setzt voraus, dass jedes Album einen einzelnen Künstler hat. Es ist nicht möglich, unterschiedliche Interpreten pro Titel oder viele Interpreten pro Album oder Titel zu haben. Es ist in der Tat keine sehr gute Darstellung der realen Welt.
Ypercubeᵀᴹ

1
@TimAbell Ich denke, das ist ein Missgeschick von Workbench, in dem die Diagramme erstellt wurden (aufgrund der Reihenfolge der Spalten in den PKs wird es nicht wie die Album-AlbumTrack-Verbindung erkannt)
ypercubeᵀᴹ

2

Leider habe ich nicht genug Repräsentanten, um Kommentare abzugeben um die Antwort ypercube , daher werde ich stattdessen eine alternative Antwort posten. Ich stimme dieser Antwort im Allgemeinen zu, denke jedoch, dass der Primärschlüssel und die eindeutigen Einschränkungen AlbumTrack falsch sind, da Alben und Tracks beide schwach sind Entitäten. Beispielsweise würden die folgenden gültigen Daten mit den vorgeschriebenen Einschränkungen nicht zugelassen:

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

Stattdessen würde ich setzen PRIMARY KEY (artistID, albumID, trackID) die eindeutige Einschränkung und löschen, was zu Folgendem führt:

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

Titel dürfen weiterhin höchstens einmal pro Album vorkommen.

Außerdem gibt die Frage nicht an, dass Tracks schwache Entitäten sind (nur Alben). Wenn Tracks tatsächlich unabhängig von Interpreten existieren können, werden die Trackund AlbumTrack-Tabellen leicht unterschiedlich definiert:

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)
) ;
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.