Správně, problém je v tom, že chcete, aby pouze jeden objekt jednoho podtypu odkazoval na jakýkoli daný řádek nadřazené třídy. Počínaje příkladem, který uvedl @Jay S, zkuste toto:
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)
);
Toto je příklad disjunktních podtypů zmíněných @mike g.
Komentáře od @Countably Infinite a @Peter:
INSERT do dvou tabulek by vyžadoval dva příkazy vložení. Ale to platí také v SQL, kdykoli máte podřízené tabulky. Je to běžná věc.
UPDATE může vyžadovat dva příkazy, ale některé značky RDBMS podporují UPDATE s více tabulkami se syntaxí JOIN, takže to můžete provést jedním příkazem.
Při dotazování na data to můžete udělat jednoduše dotazem na media
pokud potřebujete pouze informace o běžných sloupcích:
SELECT name, url FROM media WHERE media_id = ?
Pokud víte, že se dotazujete na film, můžete získat informace specifické pro film jediným spojením:
SELECT m.name, v.release_date
FROM media AS m
INNER JOIN movies AS v USING (media_id)
WHERE m.media_id = ?
Pokud chcete informace pro daný záznam média a nevíte, o jaký typ se jedná, museli byste se připojit ke všem tabulkám podtypů s vědomím, že bude odpovídat pouze jedna taková tabulka podtypů:
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 = ?
Pokud je daným médiem film, pak všechny sloupce v t.*
bude NULL.