2015-01-20 136 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