在表之间的识别和非识别关系的上下文中,MySQL 的文档将很多表称为父表和子表。
如何确定哪个表是父表,哪个表是子表?
子表(AKA弱实体)是主键属性依赖于另一个表的表,因此子表由它所依赖的表(父表)中的行标识或部分标识。如果没有父表中的相应行,子表中的行就不能存在。
为了说明,让我们举一个我们都熟悉的简单且完全相关的例子:家庭背景下的父母和孩子。我们可以用这样的表来模拟这种关系:
在上面的模型中,Parents
表中的每一行都由一个唯一标识SSN
。是每个父级的SSN
固有且唯一的属性,因此它是独立的或“强”实体,因为它不依赖另一个表来定义其身份。
但是,子项需要父项才能存在(Parent_SSN
必须SSN
引用表中的现有Parents
项)。
请注意表中的复合主键 ( Parent_SSN, Name
) Children
。这意味着通过 和 的组合来唯一标识子项。您不能仅根据该字段查询单个孩子,因为多个父母可能有同名的孩子。同样,您不能仅根据字段查询单个子项,因为一个父项可能有多个子项。考虑到这一点,孩子被他们的父母部分识别,从而识别关系。Parent_SSN
Name
Name
Parent_SSN
但是,SSN 也不能唯一标识儿童吗?为什么是的,当然。让我们继续调整我们的模型以包括:
在这个版本的模型中,请注意我们已经SSN
为Children
. 儿童的独特身份现在由他们自己内在和独特的定义SSN
。他们的身份不再依赖于Parents
桌子。尽管该Parent_SSN
字段仍然引用表SSN
的,但它与孩子的唯一身份无关,因此父母与其孩子有非识别关系,现在两个表都可以被认为是“强”独立实体。Parents
顺便说一句,这个版本的模型比第一个版本有一些优势:
Parent_SSN
字段包含NULL
以说明您拥有有关孩子的数据但不知道他/她的父母是谁的事件。在上述两种模型中,Parents
表都被认为是表的父Children
表。但是,在第二个模型中的非标识关系中,Parents
它只是外键上下文中的父表,Parent_SSN
因为在表中Parent_SSN
引用/依赖,但在定义子项的实际身份时没有任何作用。SSN
Parents
为了说明为什么在决定哪些表是父/子表时上下文很重要,请考虑以下涉及循环依赖的示例:
在此示例中,员工和部门由他们自己的属性唯一标识,并且不会从其他表中派生其身份的任何部分。
在这里,我们有两个非标识关系:一个员工为一个部门工作(DeptNo
在Employee
表中),一个部门由一个员工管理(ManagerSSN
在Department
表中)。哪个是父表?...儿童桌?
这取决于上下文——你在说哪个外键关系?Department 表将被视为表上下文中的父表,DeptNo
因为Employee
它DeptNo
引用/依赖于Department
表。
但是,Employee 表将被视为表上下文中的父表,ManagerSSN
因为Department
它ManagerSSN
引用/依赖于Employee
表。
没有严格的规则可以确定表在关系中的角色。事实上,这就是关系模型的美妙之处和创新之处:没有层次结构。
通常,如果从某个表到另一个表存在硬依赖关系,则子角色或父角色由表的语义确定。示例:在 a order
,order_details
关系中,很明显那order
是父母和order_details
孩子。
在其他情况下,不清楚关系在关系中扮演什么角色。例子:orders
和customers
关系。如果您执行查询以获取orders
属于某个特定的所有内容,customer
则父级可能是customers
并且orders
是子级。但是您也可以进行查询以获取customers
特定 的所有装运信息(以相关方式存储)order
,在这种情况下,您可能会争辩说在此查询中它order
是父节点,而子节点是子节点。customers
正如我之前所说,当关系模型在 70 年代后期被发明时,它相对于一种主流范式(分层数据模型)的主要优势之一是能够查找相关数据而不管它们的依赖关系。
这里提出了一个很好的定义:
标识关系是子表中的行的存在依赖于父表中的行。(...) 形式上,“正确”的做法是使外键[即父主键]成为子主键的一部分。