PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Polimorfismo nelle tabelle del database SQL?

Giusto, il problema è che vuoi che solo un oggetto di un sottotipo faccia riferimento a una determinata riga della classe genitore. Partendo dall'esempio fornito da @Jay S, prova questo:

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

Questo è un esempio dei sottotipi disgiunti menzionati da @mike g.

Re commenti di @Countably Infinite e @Peter:

INSERT su due tabelle richiederebbe due istruzioni di inserimento. Ma questo è vero anche in SQL ogni volta che hai tabelle figlio. È una cosa normale da fare.

UPDATE potrebbe richiedere due istruzioni, ma alcuni marchi di RDBMS supportano UPDATE multi-table con sintassi JOIN, quindi puoi farlo in un'unica istruzione.

Quando esegui una query sui dati, puoi farlo semplicemente interrogando il media tabella se hai bisogno solo di informazioni sulle colonne comuni:

SELECT name, url FROM media WHERE media_id = ?

Se sai che stai interrogando un film, puoi ottenere informazioni specifiche sul film con un unico join:

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

Se desideri informazioni per una determinata voce multimediale e non sai di che tipo si tratta, dovresti unirti a tutte le tabelle di sottotipi, sapendo che solo una di queste tabelle di sottotipi corrisponderà:

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

Se il file multimediale specificato è un film, tutte le colonne in t.* sarà NULL.