Много ко многим и слабым сущностям


16

У меня есть сущность, которая не может существовать без определения другой, и я хочу, чтобы эта сущность участвовала в отношениях «многие ко многим».

Пример: у исполнителя есть альбом (альбом не может существовать без исполнителя), альбом также имеет много дорожек, но одна и та же дорожка может существовать во многих альбомах.

Так что между альбомом и треками у нас есть отношения многие ко многим.

Если альбом является слабой сущностью, то его первичным ключом является внешний ключ, ссылающийся на исполнителя, поэтому он не может быть внешним ключом для другой таблицы, представляющей отношение «многие ко многим».

Вопрос в том, возможно ли иметь такие отношения в SQL, и если да, то как их выразить?


Нет, первичным ключом альбома будет целое число, делающее альбом уникальным. Затем вы можете иметь artist_idвнешний ключ, который ссылается на художника. Если вы хотите, чтобы одна дорожка была сопоставлена ​​с несколькими альбомами, используйте таблицу сопоставления с track_id, album_id. Легко :)
Philᵀᴹ

Ответы:


16

Я думаю, что вы можете, используя «алмазную» диаграмму отношений:

диаграмма

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 Вам имеет смысл добавить следующие уникальные ограничения в таблицу AlbumTrack: (trackID, albumID) и (albumID, trackNo)?
АК

@AlexKuznetsov Вы правы, спасибо. Я «уменьшу» PK к вашему предложению (albumID, trackNo)и добавлю другое ограничение Unique.
ypercubeᵀᴹ

1
Не забудьте разрешить для альбомов, у которых нет ни одного номинального исполнителя, либо с помощью фиктивного исполнителя с именем «Разные» или аналогичного, либо путем обнуления столбца исполнителя таблицы альбома. На самом деле, у вас может быть более одного исполнителя на трек, поэтому вам может понадобиться аранжировка «многие ко многим».
Дэвид Спиллетт

1
@DavidSpillett Да, мы могли бы сделать это, но это усложнит ситуацию и изменит форму задаваемого вопроса. Вопрос предполагает / диктует, что у каждого альбома есть один исполнитель. Невозможно иметь разных исполнителей на трек, ни много исполнителей на альбом или трек. Это действительно не очень хорошее представление о реальном мире.
ypercubeᵀᴹ

1
@TimAbell Я думаю, что это ошибка из Workbench, где были созданы диаграммы (не распознавая его так же, как соединение Album-AlbumTrack из-за порядка столбцов в PK)
ypercubeᵀᴹ

2

К сожалению, у меня недостаточно представителей, чтобы комментировать ответ ypercubeᵀᴹ , поэтому вместо этого я опубликую альтернативный ответ - я в целом согласен с этим ответом, но считаю, что первичный ключ и уникальные ограничения AlbumTrack неверны, поскольку альбомы и треки слабые юридические лица. Например, следующие допустимые данные с предписанными ограничениями будут запрещены:

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

Вместо этого я бы установил PRIMARY KEY (artistID, albumID, trackID)и исключил уникальное ограничение, в результате чего:

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

Треки все еще ограничены, чтобы встречаться не более одного раза на альбом.

Кроме того , вопрос на самом деле не указать , что треки слабые объекты (только то , что альбомы) - если следы на самом деле может существовать независимо от художников, как Trackи AlbumTrackтаблицы слегка определяется по- разному:

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)
) ;
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.