PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Polymorphisme dans les tables de base de données SQL ?

À droite, le problème est que vous ne voulez qu'un seul objet d'un sous-type pour référencer une ligne donnée de la classe parent. En partant de l'exemple donné par @Jay S, essayez ceci :

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

Ceci est un exemple des sous-types disjoints mentionnés par @mike g.

Concernant les commentaires de @Countably Infinite et @Peter :

INSERT à deux tables nécessiterait deux instructions d'insertion. Mais c'est également vrai en SQL chaque fois que vous avez des tables enfants. C'est une chose ordinaire à faire.

UPDATE peut nécessiter deux instructions, mais certaines marques de RDBMS prennent en charge UPDATE multi-tables avec la syntaxe JOIN, vous pouvez donc le faire en une seule instruction.

Lorsque vous interrogez des données, vous pouvez le faire simplement en interrogeant le media table si vous n'avez besoin que d'informations sur les colonnes communes :

SELECT name, url FROM media WHERE media_id = ?

Si vous savez que vous interrogez un film, vous pouvez obtenir des informations spécifiques au film avec une seule jointure :

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

Si vous voulez des informations pour une entrée de média donnée, et que vous ne savez pas de quel type il s'agit, vous devrez vous joindre à toutes vos tables de sous-types, sachant qu'une seule de ces tables de sous-types correspondra :

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 le média donné est un film, alors toutes les colonnes de t.* sera NULL.