PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Polymorphismus in SQL-Datenbanktabellen?

Richtig, das Problem ist, dass nur ein Objekt eines Untertyps auf eine bestimmte Zeile der übergeordneten Klasse verweisen soll. Versuchen Sie ausgehend von dem Beispiel von @Jay S Folgendes:

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

Dies ist ein Beispiel für die disjunkten Untertypen, die von @mike g erwähnt werden.

Zu Kommentaren von @Countably Infinite und @Peter:

INSERT in zwei Tabellen würde zwei Insert-Anweisungen erfordern. Aber das gilt auch in SQL, wenn Sie untergeordnete Tabellen haben. Es ist eine ganz normale Sache.

UPDATE erfordert möglicherweise zwei Anweisungen, aber einige RDBMS-Marken unterstützen UPDATE für mehrere Tabellen mit JOIN-Syntax, sodass Sie dies in einer Anweisung tun können.

Wenn Sie Daten abfragen, können Sie dies einfach tun, indem Sie media abfragen Tabelle, wenn Sie nur Informationen über die gemeinsamen Spalten benötigen:

SELECT name, url FROM media WHERE media_id = ?

Wenn Sie wissen, dass Sie einen Film abfragen, können Sie filmspezifische Informationen mit einem einzigen Join abrufen:

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

Wenn Sie Informationen zu einem bestimmten Medieneintrag wünschen und nicht wissen, um welchen Typ es sich handelt, müssen Sie alle Ihre Untertyptabellen verknüpfen, da Sie wissen, dass nur eine solche Untertyptabelle zutrifft:

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 = ?

Wenn das angegebene Medium ein Film ist, dann alle Spalten in t.* wird NULL sein.