正如评论中所指出的,提供示例 DDL 并使用模式通常有助于您自己了解它并帮助其他人更有效地响应。看看这个 DB Fiddle,看看它是否准确地代表了你想要描述的内容。
create table t1 (
i int not null primary key
);
create table t2 (
i int not null primary key
foreign key references t1(i)
on delete cascade
);
create table t3 (
i int not null primary key
foreign key references t2(i)
on delete cascade
);
create table t4 (
i int not null primary key
foreign key references t3(i)
on delete cascade
);
alter table t4
add constraint fk_t4_t1
foreign key (i)
references t1(i);
select v.v,
t1.i t1,
t2.i t2,
t3.i t3,
t4.i t4
from (values (1),(2),(3),(4),(5)) v (v)
left join t4 on t4.i = v.v
left join t3 on t3.i = v.v
left join t2 on t2.i = v.v
left join t1 on t1.i = v.v;
FK 约束表示引用表的 FK 列的子行值必须是被引用表的相应列的唯一子行值——可能是 PK(主键)子行值。
每当T (...) references U (...)& U (...) references V (...),T (...) references V (...)对于一些适当的列顺序。我们通过说 FK 约束是可传递的来描述这一点。我们会说后一个 FK 约束是可传递的,并且由前 2 个或任何更长的引用链隐含或者是其结果。如果我们声明/强制执行前 2,我们不需要声明/强制执行后者,因为声明/强制执行前者会强制执行后者。未声明的传递 FK 约束一直是设计的一部分。
冗余外键或冗余引用
有关来自该网络的与此(某种)相关的实际用例查询的随机抽样,请参见此处和此处。
也许?大概?如果我在审查时遇到它,我肯定会闻到一股代码味道。是否采取行动来改变它(或实施它)需要比目前帖子中更多的信息;并且可能出于“互联网这么说”之外的实际原因而这样做。
TL;博士:
正如评论中所指出的,提供示例 DDL 并使用模式通常有助于您自己了解它并帮助其他人更有效地响应。看看这个 DB Fiddle,看看它是否准确地代表了你想要描述的内容。
如您所见,完全可以定义您描述的关系(至少在我的小提琴平台上),甚至可以强制执行级联关系。但是...如果您尝试将
CASCADE
操作应用于循环定义的关系,您可能会看到这一点(同样,取决于您的平台)......数据库引擎会保护您免受自己的伤害;除非你在一些疯狂的奇异 DBMS 中,比如
CASCADE
允许冗余的PostgreSQL 。如果您想可视化适合这种模型的物化关系,它可能看起来像这样......
...这可能表明...
还值得注意的是,前面的小提琴使用和
X->X->X
“交叉键”样式映射(我已经看到“在野外”以合理的效果使用) - 尽管你的更严格地是......如果实体真正不同,则对模型的另一种可能解释是
X->Y->Z
专用键映射,如本小提琴所示,对冲突级联有其独特的反应。FK 约束表示引用表的 FK 列的子行值必须是被引用表的相应列的唯一子行值——可能是 PK(主键)子行值。
每当
T (...) references U (...)
&U (...) references V (...)
,T (...) references V (...)
对于一些适当的列顺序。我们通过说 FK 约束是可传递的来描述这一点。我们会说后一个 FK 约束是可传递的,并且由前 2 个或任何更长的引用链隐含或者是其结果。如果我们声明/强制执行前 2,我们不需要声明/强制执行后者,因为声明/强制执行前者会强制执行后者。未声明的传递 FK 约束一直是设计的一部分。您似乎有 T4 参考 T3 参考 T2 参考 T1 和 T4 参考 T1。T4 引用 T1 是可传递的,由其他引用。所以它的声明和箭头是不必要的/多余的。我们可以将图表描述为具有冗余箭头。
如果我们有 T1 引用 T4 而不是 T4 引用 T1,那将合理地称为(定向)FK(外键)(约束)循环。
当有一个循环以相同的 FK 列集开始和结束时,结果是某个表中没有空值的每个 FK 子行值必须唯一地出现在相应列下的每个表中。(带有 NULL 的子行的详细信息取决于 FK MATCH 模式。)
(在关系模型中,当同一组子行值必须出现在两个地方——不一定是唯一的——它被称为 EQD(平等依赖)约束。)
如果 FK 列在表的某些子集中全部为 NOT NULL,那么您可以使用适当的列相等性将该子集替换为其表的 INNER JOIN。你可以只有一张桌子。
带有循环的设计不一定是坏事——但如果所有 FK 目标都是 PK 或 UNIQUE NOT NULL,为什么不只有一个表?但是在某些情况下,我们可能希望为了清晰、对称、性能或其他原因而保持循环。
通过分解归一化到更高的 NF 总是会引入这些循环。但是我们通常会决定更改我们的设计,让一个组件拥有比原始设计更多的行,这会将一个或多个 FK 从该组件转移到其他组件。
当前的 SQL DBMS 碰巧不允许 FK 循环,尽管这样做很简单。因此,通常不能声明一个 FK,并且必须由触发器强制执行。(当然,这种不对称性抵消了我们可能在单独的表格中寻求的对称性。)