sql >> Base de Datos >  >> RDS >> PostgreSQL

Polimorfismo en tablas de base de datos SQL?

Correcto, el problema es que desea que solo un objeto de un subtipo haga referencia a cualquier fila dada de la clase principal. A partir del ejemplo dado por @Jay S, intente esto:

create table media_types (
  media_type     int primary key,
  media_name     varchar(20)
);
insert into media_types (media_type, media_name) values
  (2, 'TV series'),
  (3, 'movie');

create table media (
  media_id       int not null,
  media_type     not null,
  name           varchar(100),
  description    text,
  url            varchar(255),
  primary key (media_id),
  unique key (media_id, media_type),
  foreign key (media_type) 
    references media_types (media_type)
);

create table tv_series (
  media_id       int primary key,
  media_type     int check (media_type = 2),
  season         int,
  episode        int,
  airing         date,
  foreign key (media_id, media_type) 
    references media (media_id, media_type)
);

create table movies (
  media_id       int primary key,
  media_type     int check (media_type = 3),
  release_date   date,
  budget         numeric(9,2),
  foreign key (media_id, media_type) 
    references media (media_id, media_type)
);

Este es un ejemplo de los subtipos disjuntos mencionados por @mike g.

Re comentarios de @Countably Infinite y @Peter:

INSERTAR en dos tablas requeriría dos declaraciones de inserción. Pero eso también es cierto en SQL cada vez que tiene tablas secundarias. Es algo normal de hacer.

UPDATE puede requerir dos declaraciones, pero algunas marcas de RDBMS admiten UPDATE de varias tablas con sintaxis JOIN, por lo que puede hacerlo en una sola declaración.

Al consultar datos, puede hacerlo simplemente consultando los media tabla si solo necesita información sobre las columnas comunes:

SELECT name, url FROM media WHERE media_id = ?

Si sabe que está consultando una película, puede obtener información específica de la película con una sola unión:

SELECT m.name, v.release_date
FROM media AS m
INNER JOIN movies AS v USING (media_id)
WHERE m.media_id = ?

Si desea información para una entrada de medios determinada y no sabe de qué tipo es, debe unirse a todas sus tablas de subtipos, sabiendo que solo una de esas tablas de subtipos coincidirá:

SELECT m.name, t.episode, v.release_date
FROM media AS m
LEFT OUTER JOIN tv_series AS t USING (media_id)
LEFT OUTER JOIN movies AS v USING (media_id)
WHERE m.media_id = ?

Si el medio dado es una película, entonces todas las columnas en t.* será NULL.