Tak, problem polega na tym, że chcesz, aby tylko jeden obiekt jednego podtypu odwoływał się do dowolnego wiersza klasy nadrzędnej. Zaczynając od przykładu podanego przez @Jay S, spróbuj tego:
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)
);
To jest przykład rozłącznych podtypów wspomnianych przez @mike g.
Ponownie komentarze @Countably Infinite i @Peter:
INSERT do dwóch tabel wymagałoby dwóch instrukcji INSERT. Ale dotyczy to również SQL za każdym razem, gdy masz tabele podrzędne. To zwyczajna rzecz.
UPDATE może wymagać dwóch instrukcji, ale niektóre marki RDBMS obsługują wiele tabel UPDATE ze składnią JOIN, więc możesz to zrobić za pomocą jednej instrukcji.
Podczas wysyłania zapytań do danych możesz to zrobić po prostu, wysyłając zapytanie do media
tabela, jeśli potrzebujesz tylko informacji o wspólnych kolumnach:
SELECT name, url FROM media WHERE media_id = ?
Jeśli wiesz, że pytasz o film, możesz uzyskać informacje dotyczące filmu za pomocą jednego połączenia:
SELECT m.name, v.release_date
FROM media AS m
INNER JOIN movies AS v USING (media_id)
WHERE m.media_id = ?
Jeśli potrzebujesz informacji dla danego wpisu mediów, a nie wiesz, jaki to typ, musiałbyś dołączyć do wszystkich swoich tabel podtypów, wiedząc, że tylko jedna taka tabela podtypów będzie pasować:
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 = ?
Jeśli podanym nośnikiem jest film, to wszystkie kolumny w t.*
będzie NULL.