当两个表具有多对多关系或者表与自身具有多对多关系时,我们可以使用联结表对其进行建模。
然而,关系的类型可以超出原始类型,例如:
要求:我们有用户。每个用户可以有0个或更多其他用户作为朋友
解决方案:一个名为" user_user"的用户表和联结表。
然后我们发现了一个新的要求:一些友谊是浪漫的,换句话说,两个用户可以以不同于友谊的方式连接。
解决方案a:在包含友谊类型(朋友|伙伴|前朋友)等的联结表中添加一列。
解决方案b:重命名' user_user'表与友谊' (这可能是一个更好的名称,从这种方法开始)并创建一个名为浪漫的新表,也将用户连接到用户。
然后我们又发现了另一个新要求:用户可以欠其他用户的钱。我们再次可以搭载在同一个交汇处或创建一个名为“债务”的新账户。这次我的直觉是100%有一个单独的表。
每次我们发现新类型的关系或知道关系的子类型时,我们都可以在一个联结表中添加一列或创建新的联结表。
我的问题是,决定何时必须创建新表的好规则是什么?
当我们每个订购对必须有多行时,是吗?例如,如果从未删除过去的关系,那么如果两个用户过去已经是朋友两年,失去联系,然后重新成为朋友,我们希望旧行也有开始和结束日期,但有两行使其他列信息重复(旧行显示用户欠钱,新行显示没有)。
是否额外列在逻辑上不是单一类型关系的定义?
好的:友谊日期的开始直接与友谊1对1相关
不行:一个用户拥有另一个用户多少钱的列可以是1比1的关系,但逻辑上不是友情的描述。
如果我们事先知道两个表将有很多对多关系,那么计划多个联结表还是使单个联结表更灵活(即使类型为连接不是任意的)?
答案 0 :(得分:0)
TL; DR 表格代表应用程序/业务关系/关联。与在Entity- Relationship 模型中一样。即关系。与 Relational 模型中一样。每次我们对不同的关系感兴趣时,我们都会考虑一个新的(“联结”/“关联”)表。 规范化告诉我们何时以及如何将关系/表分解为其他人或将其合并为一个。
我们通过一些谓词(即语句模板)来确定一个关系,一行是命题,即语句,它表示我们对应用程序感兴趣的内容。从表的谓词中生成true语句的行放在表中。
Employee(e, n, ...) -- employee identified by E is named N and ...
Manages(e, m) -- employee M manages employee E
您无法知道表格中有关应用程序的内容或根据应用程序设置它而不知道其谓词!当你陈述“关系”的“基数”时,你必须先确定你正在谈论的关系/关联/谓词。
(不幸的是,“关系”被许多所谓的ER方法和产品用来表示表的外键。)
我们可以将多个表组合成一个表,或者当我们可以从新表中重构原始表时替换其他表。在这里,我们可以将上面的表格合并到
中-- employee identified by E is named N and ... AND employee M manages employee E
EmployeeM(e, n, ..., m)
这恰好是员工和员工的联接。管理,因为JOIN的谓词是其参数的谓词的AND。但是因为E是一组共同的列和&它在其中一个中是独一无二的,我们可以通过新的投影重建原件。
当员工只能拥有确切的一个经理时,这将是一个合理的设计。但是,如果一个员工可以拥有一个或多个管理器,那么该表虽然仍然包含满足该谓词并允许重建原件的行,但会显示更新异常,因此我们更喜欢原件。如果员工可以拥有零或一个或零或更多管理员,那么我们仍然可以使用该表,但不仅该表,因为它无法告诉我们没有经理的员工。 (原始设计的作用。)我们还需要一个像一样的员工表,但是不同的谓词 employee identified by E is named N and ... AND E has no manager.
或者我们可以使用这两个表而不是只是一个表喜欢 EmployeeM,但它允许 nulls 通过不同的谓词 employee identified by E is named N and ... AND ( employee M manages employee E OR M IS NULL AND E has no manager )
。
了解原始的陈尔模型/方法,其中有实体类型,图标&表格和关系类型,图标和表。每种关系类型都清楚地表示为钻石。每一行都清楚地表示关系类型中实体类型(可能是关联实体类型)的参与,即清楚地表示表之间的FK。而许多所谓的ER方法甚至不能区分实体和关系。 (这不一定是好的或坏的,但他们的陈述往往不解释如何正确建模。)
关系模型本身并不关心实体和关系。它的表只是值上的关系。 ER和所谓的ER方法在实体和关系之间做出了不必要的和有限的任意区分。当然,表格仍然可以说明它在ER模型中对应用程序的作用,因为值的子行可以识别实体。请参阅this answer。
规范化告诉您何时以及如何将关系的谓词/表格分解为较小的谓词/表格(即它的投影,AND / JOIN返回它),它会告诉您何时&如何将多个关系的谓词/表组合成一个(通过AND / JOIN,使用投影重建)。
PS重复值本身没有任何问题。可能存在的问题是,根据您选择的谓词,多行在应用程序中存在或不在表中时表示相同的事情。并非所有这些冗余都是错误的;这只是不受控制的冗余是错误的。一般来说,我们希望设计尽可能多的5NF。 (即减少更新异常,谓词复杂性和约束。)
答案 1 :(得分:0)
由你决定。你可以定义一个友谊"不同于"浪漫参与"所以需要两个连接表。或者你可以定义"浪漫参与"作为友谊的一个特例"所以需要一张桌子。我倾向于后者更简单,更容易混淆。 (如果同样的两个人被列为朋友和恋人,会怎么样?)
然而,"欠钱"是不同的。如果A是B的朋友,那么B就是A的朋友。但是如果A欠B的钱,说B欠A的钱是错误的。所以你不仅要定义一种不同的关系,而且定位于哪个字段包含对A的引用,并且包含对B的引用变得重要。为此,最好有一个单独的联结表。