Certo, o problema é que você deseja que apenas um objeto de um subtipo faça referência a qualquer linha da classe pai. A partir do exemplo dado por @Jay S, tente isto:
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 é um exemplo dos subtipos disjuntos mencionados por @mike g.
Re comentários de @Countably Infinite e @Peter:
INSERT para duas tabelas exigiria duas instruções de inserção. Mas isso também é verdade no SQL sempre que você tiver tabelas filhas. É uma coisa comum de se fazer.
UPDATE pode exigir duas instruções, mas algumas marcas de RDBMS suportam UPDATE multi-tabela com sintaxe JOIN, então você pode fazer isso em uma instrução.
Ao consultar dados, você pode fazer isso simplesmente consultando o
media
table se você precisar apenas de informações sobre as colunas comuns:SELECT name, url FROM media WHERE media_id = ?
Se você sabe que está consultando um filme, pode obter informações específicas do filme com uma única junção:
SELECT m.name, v.release_date
FROM media AS m
INNER JOIN movies AS v USING (media_id)
WHERE m.media_id = ?
Se você deseja informações para uma determinada entrada de mídia e não sabe de que tipo é, você teria que juntar todas as suas tabelas de subtipos, sabendo que apenas uma dessas tabelas de subtipos corresponderia:
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 a mídia fornecida for um filme, todas as colunas em
t.*
será NULO.