Muitas para muitas e entidades fracas


16

Eu tenho uma entidade que não pode existir sem ser definida por outra e quero que essa entidade participe de um relacionamento muitos-para-muitos.

Exemplo: um artista tem um álbum (o álbum não pode existir sem um artista), o álbum também tem muitas faixas, mas a mesma faixa pode existir em muitos álbuns.

Portanto, temos uma relação de muitos para muitos entre o álbum e as faixas.

Se o álbum é uma entidade fraca, sua chave primária é uma chave estrangeira que faz referência ao artista, portanto, não pode ser uma chave estrangeira para outra tabela que representa um relacionamento muitos-para-muitos.

A questão é: é possível ter esse tipo de relacionamento no SQL e, se sim, como eu o expresso?


Não, a chave primária do álbum seria apenas um número inteiro que torna o álbum único. Você pode ter uma artist_idchave estrangeira que faz referência ao artista. Se você deseja que uma única faixa seja mapeada para vários álbuns, use uma tabela de mapeamento com track_id, album_id. Fácil :)
Philᵀᴹ

Respostas:


16

Eu acho que você pode, usando um diagrama de relacionamento "diamante":

diagrama

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

11
+1 faria sentido adicionar as seguintes restrições exclusivas à tabela AlbumTrack: (trackID, albumID) e (albumID, trackNo)?
AK

@AlexKuznetsov Você está certo, thnx. Vou "encolher" o PK ao seu sugerido (albumID, trackNo)e adicionar a outra restrição Exclusiva também.
precisa saber é o seguinte

11
Lembre-se de permitir álbuns que não têm um artista nominal único, seja com um artista fictício chamado "Various" ou similar ou com a coluna do artista da tabela de álbuns anulável. Na verdade, você pode ter mais de um artista por faixa, portanto pode ser necessário um arranjo muitos para muitos também.
David Spillett 25/09

11
@DavidSpillett Sim, poderíamos fazer isso, mas isso complicaria as coisas e se desviaria da pergunta. A pergunta assume / determina que todo álbum tem um único artista. Não é possível ter artistas diferentes por faixa, nem muitos artistas por álbum ou faixa. Não é uma representação muito boa do mundo real, de fato.
usar o seguinte código

11
@TimAbell eu pensar que é um contratempo de Workbench onde os diagramas foram criados (que não reconhecem o mesmo que a ligação Álbum-AlbumTrack devido à ordem de colunas nas PKs)
ypercubeᵀᴹ

2

Infelizmente, não tenho representante suficiente para comentar a resposta do ypercubeᵀᴹ , por isso vou postar uma resposta alternativa - concordo com essa resposta em geral, mas acho que a chave primária e as restrições exclusivas AlbumTrack estão incorretas, uma vez que os álbuns e as faixas são fracos entidades. Por exemplo, os seguintes dados válidos seriam proibidos, com as restrições prescritas:

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

Em vez disso, eu definiria PRIMARY KEY (artistID, albumID, trackID)e eliminaria a restrição exclusiva, resultando em:

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

As faixas ainda estão limitadas a ocorrer no máximo uma vez por álbum.

Além disso, a questão não especifica que as faixas são entidades fracas (apenas os álbuns) - se as faixas podem existir independentemente dos artistas, as tabelas Tracke AlbumTracksão definidas de maneira um pouco diferente:

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)
) ;
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.