基于关系依赖的数据库约束
Database constraints based on relationship dependencies
我试图在数据库模式中模拟一个棘手的案例,以避免可能的不一致。下图大致描述了目前的情况,有3个table相互影响,table1和table2有N:M关系,table2 和 table3 有另一个 N:M 关系,table1 和 table3 有一个 1:N 关系。我需要以某种方式添加一个约束,这样当 table2 和 table1 之间也存在关系时,table2 和 table3 之间只能存在关系table3.
的特定实例的外键
例如,假设我们有以下 tables:
考虑到我要施加的约束,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] 没有关系
我认为你最后的外键引用引用了错误的 table。我在 PostgreSQL 中写了这个。对于 MySQL,您只需将内联约束移动到单独的约束子句中。
我认为前三个 table 和你的一样。 (但要使用更短的名称。如果您打算在问题中使用无意义的名称,至少让它们更短。)
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)
);
table "t3" 有点不同。 unique 约束看起来是多余的,其实不然。它让这对列成为外键引用的目标。
create table t3 (
t3_id integer primary key,
t1_id integer not null references t1 (t1_id),
unique (t3_id, t1_id)
);
最后一个 table、"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"
这似乎是正确的。
我试图在数据库模式中模拟一个棘手的案例,以避免可能的不一致。下图大致描述了目前的情况,有3个table相互影响,table1和table2有N:M关系,table2 和 table3 有另一个 N:M 关系,table1 和 table3 有一个 1:N 关系。我需要以某种方式添加一个约束,这样当 table2 和 table1 之间也存在关系时,table2 和 table3 之间只能存在关系table3.
的特定实例的外键例如,假设我们有以下 tables:
考虑到我要施加的约束,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] 没有关系我认为你最后的外键引用引用了错误的 table。我在 PostgreSQL 中写了这个。对于 MySQL,您只需将内联约束移动到单独的约束子句中。
我认为前三个 table 和你的一样。 (但要使用更短的名称。如果您打算在问题中使用无意义的名称,至少让它们更短。)
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)
);
table "t3" 有点不同。 unique 约束看起来是多余的,其实不然。它让这对列成为外键引用的目标。
create table t3 (
t3_id integer primary key,
t1_id integer not null references t1 (t1_id),
unique (t3_id, t1_id)
);
最后一个 table、"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"
这似乎是正确的。