2015-01-20 105 views
3

我想模擬數據庫模式中的一個棘手的情況,以避免可能的不一致。下圖大致描述了目前的情況,有3個表格互相交互,table1和table2有N:M的關係,table2和table3有另外的N:M關係,table1和table3有1:N的關係。我需要以某種方式添加一個約束,例如,當table2和table1之間存在關係時,table2和table3之間只能存在關係,而table1是table3特定實例的外鍵。基於關係依賴關係的數據庫約束

enter image description here

舉個例子,假設我們有以下的表格:

enter image description here

鑑於我想加以約束,在table3_has_table2第一行是有效的,如表3 [0x000020 ] table1 [0x0000A]爲FK,table2 [0x00010]在table1_has_table2中有table1 [0x0000A]的條目,但table3_has_table2中的第二行無效,因爲table2 [0x00011]與table1_has_table2中的table1 [0x0000A]沒有關係。

+0

在數據庫設計中,您只需要添加一個完整性限制,指出「當table2和table1之間存在關係時,只能存在table2和table3之間的關係」。如果你想在sql中實現這個約束,你可以創建一個觸發器。我也考慮過數據庫設計中的其他選擇,但我認爲所有其他方案都會違反其他規則之一,或者有重複的數據(如果僅以一種關係表示table1_has_table2和table2_has_table3)。 – 2015-01-20 22:58:19

回答

2

我認爲你最後的外鍵引用引用了錯誤的表。我在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" 

這似乎是正確的。

+0

太棒了,這似乎解決了我的問題,現在我只需要弄清楚如何做與django類似的東西。 – AnilM3 2015-01-21 19:06:51