TL;DR
再问:
child
PARENT_ID // <-- Should this column be here?
是,如果从child.PARENT_ID添加外键约束引用父列parent.PARENT_ID,则将强制执行父子关系的完整性。
表parent_has_children应该存在吗?
否,这样的链接或联合表用于建模many-many 关系。表P 和C 之间的多对多关系意味着相同的C 行可以同时关联许多P 行,反之亦然。这显然不是亲子关系。
建模一对多关系
如果关系是 1 个父级与多个子级(即同一个子级只能属于一个父级),则标准建模方法是通过父键(其中一个)从子表中引用父表列,通常是父主键 (PK)。同时,对引用列 (child.PARENT_ID) 进行外键 (FK) 约束也是一个好主意,以鼓励 RDMBS 在整个关系中强制执行 referential integrity:
parent
-------------
PARENT_ID PRIMARY KEY, // PK for the parent table
OTHER_COL
...
child
-------------
CHILD_ID PRIMARY KEY, // PK for the Child Table
PARENT_ID // <-- Should this column be here? = Yes
CONSTRAINT FK_ChildParent FOREIGN KEY(PARENT_ID) REFERENCES parent(PARENT_ID)
OP 的额外 many:many 表 parent_has_children 是多余的,因为每个 child 将只有一行,并且很快就会成为保留此表 in sync 并从另一个表中添加/删除行的负担表(因为未能保持同步将导致关系完整性的混乱/矛盾)。
Re : 父母如何了解自己的孩子?
可以使用在父外键列上过滤的子表上的简单查询找到给定父级的子记录:
SELECT ...
FROM child
WHERE PARENT_ID = myParentId;
由于这通常是一个常见的查询,确保外键 child.PARENT_ID 被索引总是一个好主意 - 一些 RDBMS 版本默认为所有外键执行此操作。
CREATE INDEX IXFoo on child(PARENT_ID);
如果您在表示这些表的应用程序中有一个实体模型(例如,用于 ORM),则父实体通常会有一个包含其 child 实例的集合,而在子实体上,标量外键 child.PARENT_ID 'column' 要么完全删除,要么替换为对父实例的引用:
class Parent
{
ParentId,
Child[] Children,
// ...
}
class Child
{
ChildId,
Parent Parent, // Optional, allows bidirectional navigation
// ...
}