Muchas a muchas y entidades débiles


16

Tengo una entidad que no puede existir sin ser definida por otra, y quiero que esta entidad participe en una relación de muchos a muchos.

Ejemplo: un artista tiene un álbum (el álbum no puede existir sin un artista), el álbum también tiene muchas pistas, pero la misma pista puede existir en muchos álbumes.

Así que tenemos una relación de muchos a muchos entre el álbum y las pistas.

Si el álbum es una entidad débil, entonces su clave principal es una clave externa que hace referencia al artista, por lo tanto, no puede ser una clave externa para otra tabla que represente una relación de muchos a muchos.

La pregunta es: ¿es posible tener este tipo de relación en SQL, y si es así, cómo lo expreso?


No, la clave principal del álbum sería un número entero que hace que el álbum sea único. Entonces puede tener una artist_idclave externa que hace referencia al artista. Si desea asignar una sola pista a varios álbumes, utilice una tabla de asignación con track_id, album_id. Fácil :)
Philᵀᴹ

Respuestas:


16

Creo que puedes, usando un diagrama de relación "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
) ;

1
+1 ¿Tendría sentido agregar las siguientes restricciones únicas a la tabla AlbumTrack: (trackID, albumID) y (albumID, trackNo)?
AK

@ AlexKuznetsov Tienes razón, gracias. "Reduciré" el PK a su sugerencia (albumID, trackNo)y agregaré la otra restricción Unique, también.
ypercubeᵀᴹ

1
Recuerde permitir álbumes que no tengan un artista nominal único, ya sea teniendo un artista ficticio llamado "Varios" o similar o haciendo que la columna de artista de la tabla de álbumes sea anulable. De hecho, podría tener más de un artista por pista, por lo que también podría necesitar un arreglo de muchos a muchos.
David Spillett

1
@DavidSpillett Sí, podríamos hacer eso, pero complicaría las cosas y se desviaría de la pregunta formulada. La pregunta supone / dicta que cada álbum tiene un solo artista. No es posible tener diferentes artistas por pista, ni muchos artistas por álbum o pista. No es una muy buena representación del mundo real, de hecho.
ypercubeᵀᴹ

1
@TimAbell Creo que es un error de Workbench donde se crearon los diagramas (sin reconocerlo igual que la conexión Album-AlbumTrack debido al orden de las columnas en las PK)
ypercubeᵀᴹ

2

Desafortunadamente, no tengo suficiente representante para comentar la respuesta de ypercubeᵀᴹ , por lo que publicaré una respuesta alternativa en su lugar, estoy de acuerdo con esa respuesta en general, pero creo que la clave principal y las contracciones únicas AlbumTrack son incorrectas dado que los álbumes y las pistas son débiles entidades. Por ejemplo, los siguientes datos válidos serían, con las restricciones prescritas, no permitidos:

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

En cambio, establecería PRIMARY KEY (artistID, albumID, trackID)y soltaría la restricción única, lo que resultaría en:

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

Las pistas todavía están limitadas a ocurrir como máximo una vez por álbum.

Además, la pregunta en realidad no especifica que las pistas son entidades débiles (solo que los álbumes lo son): si las pistas pueden existir independientemente de los artistas, las tablas Tracky AlbumTrackse definen de manera ligeramente 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)
) ;
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.