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.