書籍名のすべての外部キーを省略しました。
だから私はテーブル定義の完全に強化されたセットで答えます、これは外部キーについてですよね?簡素化された例を挙げたShure。
解決すべき問題は、reading_event_discussion
のレコードでした。 その本に存在するテーマに関するものでなければなりません:
drop table book cascade;
drop table book_theme;
drop table reading_event cascade;
drop table reading_event_discussion;
create table book (
name text primary key -- new, a must because it is FK in reading_event
);
insert into book (name) values ('game of thrones'),('Database design');
create table book_theme (
bookname text references book(name), -- new
themename text
);
insert into book_theme (bookname, themename) values
('game of thrones', 'ambition'), ('game of thrones', 'power');
create table reading_event (
i SERIAL primary key,
venue text,
bookread text references book(name) -- FK is new
);
insert into reading_event (venue, bookRead) VALUES
('Municipal Library', 'game of thrones');
-- this is the solution: extended reference check
create or replace function themecheck (i integer, th text) returns boolean as $$
select
(th in (select themename from book_theme bt
join reading_event re on i=re.i and re.bookRead=bt.bookname))
$$ language sql;
create table reading_event_discussion (
i integer references reading_event(i),
themeDiscussed text check (themecheck (i, themeDiscussed))
);
-- Test statements:
-- just check data
select * from reading_event;
-- this should be ok
insert into reading_event_discussion values (1,'ambition'),(1,'power');
-- this must be refused
insert into reading_event_discussion values (1,'databases');
したがって、解決策はカスタムチェック関数を作成することです。これは他のデータベースシステムに移植できません。
この関数は複数の言語(plpgsql、pltcl、...)で記述できますが、SQL関数はクエリにインライン化できるため、より高速になる可能性があります。