我認爲你最後的外鍵引用引用了錯誤的表。我在PostgreSQL中寫了這個。對於MySQL,您只需將內聯約束條件移入單獨的約束條件。
我認爲這三張表和你的一樣。 (但具有較短的名稱。如果你想在你的問題使用無意義的名稱,至少讓他們短。)
create table t1 (
t1_id integer primary key
);
create table t2 (
t2_id integer primary key
);
create table t1_has_t2 (
t1_id integer not null references t1 (t1_id),
t2_id integer not null references t2 (t2_id),
primary key (t1_id, t2_id)
);
表「T3」是一個有點不同。唯一的約束看起來多餘,但事實並非如此。它讓這對列成爲外鍵引用的目標。
create table t3 (
t3_id integer primary key,
t1_id integer not null references t1 (t1_id),
unique (t3_id, t1_id)
);
最後一個表「t3_has_ts」不同,它需要不同的名稱。它具有重疊的外鍵約束。
create table t3_has_ts (
t3_id integer not null,
t2_id integer not null,
t1_id integer not null,
foreign key (t1_id, t2_id) references t1_has_t2 (t1_id, t2_id),
foreign key (t3_id, t1_id) references t3 (t3_id, t1_id),
primary key (t3_id, t2_id, t1_id)
);
我整數列用整數。
insert into t1 values (10), (11);
insert into t2 values (16), (17);
insert into t3 values (32, 10);
insert into t1_has_t2 values (10, 16);
insert into t1_has_t2 values (11, 17);
-- This is the row you said should succeed.
insert into t3_has_ts values (32, 16, 10);
-- And this one should fail.
insert into t3_has_ts values (32, 17, 11);
它確實失敗了。 PostgreSQL錯誤消息說
(32, 11) is not present in table "t3"
這似乎是正確的。
在數據庫設計中,您只需要添加一個完整性限制,指出「當table2和table1之間存在關係時,只能存在table2和table3之間的關係」。如果你想在sql中實現這個約束,你可以創建一個觸發器。我也考慮過數據庫設計中的其他選擇,但我認爲所有其他方案都會違反其他規則之一,或者有重複的數據(如果僅以一種關係表示table1_has_table2和table2_has_table3)。 – 2015-01-20 22:58:19