【问题标题】:Database constraints based on relationship dependencies基于关系依赖的数据库约束
【发布时间】:2015-01-20 20:55:19
【问题描述】:

我试图在数据库模式中建模一个棘手的案例,以避免可能的不一致。下图大致描述了目前的情况,有3张表相互交互,table1和table2是N:M关系,table2和table3还有N:M关系,table1和table3是1:N关系。我需要以某种方式添加一个约束,当 table2 和 table1 之间也存在关系时,table2 和 table3 之间只能存在关系,而 table1 是 table3 的特定实例的外键。

例如,假设我们有以下表格:

鉴于我要施加的约束,table3_has_table2 中的第一行是有效的,因为 table3[0x000020] 有 table1[0x0000A] 作为 FK,而 table2[0x00010] 在 table1_has_table2 中有一个条目和 table1[0x0000A],但是table3_has_table2 中的第二行无效,因为 table2[0x00011] 与 table1_has_table2 中的 table1[0x0000A] 没有关系。

【问题讨论】:

  • 在数据库设计中,您只需添加一个完整性约束,即“当 table2 和 table1 之间也存在关系时,table2 和 table3 之间只能存在关系”。如果您想在 sql 中实现该约束,您可以创建一个触发器。我还考虑了数据库设计中的其他替代方案,但我认为所有其他替代方案都违反了其他规则之一,或者有重复的数据(如果您仅在一个关系中表示 table1_has_table2 和 table2_has_table3)。

标签: mysql database database-design relational-database


【解决方案1】:

我认为您的最后一个外键引用引用了错误的表。我在 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) 不在表“t3”中

这似乎是正确的。

【讨论】:

  • 太好了,这似乎解决了我的问题,现在我只需要弄清楚如何用 django 做类似的事情。
猜你喜欢
  • 2017-12-23
  • 1970-01-01
  • 2018-07-14
  • 1970-01-01
  • 2016-07-02
  • 2013-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多