繁体   English   中英

为什么没有多对多关系?

[英]Why no many-to-many relationships?

我是第一次学习数据库和SQL。 在我正在阅读的文章(Oracle 11g:Joan Casteel的SQL)中,它说“关系数据库中不存在多对多关系”。 我理解我们要避免它们,并且我理解如何创建一个桥接实体来消除它们,但我试图完全理解“不能存在”的说法。

实际上,实际上不可能有代表多对多的关系吗?

或者它只是非常低效,因为它会导致大量的数据重复?

在我看来,后者就是这种情况,桥接实体最大限度地减少了重复数据。 但也许我错过了什么? 我没有找到一个具体的理由(或者更好的例子),它解释了为什么要避免多对多关系,无论是在文本中还是在我搜索过的任何其他地方。 我一整天都在搜索,只是重复找到相同的信息:“不要这样做,而是使用桥接实体。” 但我想问为什么。 :-)

谢谢!

想想一个像作者和书籍之间的简单关系。 作者可以写很多书。 一本书可能有很多作者。 现在,如果没有桥接表来解决多对多关系,替代方案会是什么? 您必须向Books表添加多个Author_ID列,每个作者一个。 但是你添加了多少? 2? 3? 10? 无论你选择多少,你可能会得到很多稀疏行,其中许多Author_ID值都是NULL,你很可能遇到需要“只需要一个”的情况。 那么你要么经常修改架构以试图适应,要么你施加一些人为限制(“没有书可以有超过3位作者”)来迫使事情适应。

在关系数据库中无法创建涉及两个表的真正的多对多关系。 我相信当他们说它不存在时,他们就是这么说的。 为了实现多对多,你需要一个基本上有3个字段的中间表,一个ID,一个附加到第一个表的id和一个附加到第二个表的id。

不想要多对多关系的原因就像你说它们效率非常低效并且管理与关系每一方相关的所有记录都很难,例如,如果你删除一方的记录会发生什么关系表中的记录和另一方的表格? 至少在我看来,级联删除是一个滑坡。

通常(双关语)您将使用链接表来建立多对多

就像Joe Stefanelli所描述的那样,让我们​​说你有作者和书籍

SELECT * from Author
SELECT * from Books

你会创建一个名为AuthorBooks的JOIN

然后,

SELECT * from Author a JOIN AuthorBooks ab on a.AuthorId = ab.AuthorId JOIN Books b on ab.BookId = b.BookId

希望有所帮助。

它说“关系数据库中不存在多对多关系”。

我怀疑作者只是在争议。 从技术上讲,在SQL语言中,没有办法明确声明MM关系。 这是向表格声明多个1-M关系的紧急结果。 但是,这是实现MM关系结果的常用方法,并且在关系数据库管理系统上设计的数据库中经常使用它。

我没有找到一个具体的理由(或者更好的例子)解释了为什么要避免多对多的关系,

它们应该在适合使用的地方使用,这将是更准确的说法。 有时,例如Joe Stafanelli给出的书籍和作者示例,其中任何其他解决方案效率低下并引入其他数据完整性问题。 但是,MM关系使用起来更复杂。 他们在GUI设计器中添加了更多工作。 因此,它们只应在有意义的地方使用。 如果您非常确信一个实体永远不应与多个其他实体相关联,那么无论如何都要将其限制为1-M。 例如,如果您要跟踪货件的状态,则每个货件在任何给定时间只能有一个状态。 它会使设计复杂化,并且在逻辑意义上不允许货件具有多种状态。

它是正确的。 多对多关系分为几个一对多关系。 所以基本上,没有多少关系存在!

当然,他们可以(并且确实)存在。 这听起来像是一个肥皂箱声明。 它们是许多商业应用程序所必需的。

正确完成,它们效率不高,也没有重复数据。

看看FaceBook吧。 朋友和朋友的朋友之间有多少多对多的关系? 这是一个定义明确的业务需求。

“关系数据库中不存在多对多关系”的说法。 显然是假的。

多对多关系实际上非常有用,也很常见。 例如,考虑一个联系人管理系统,它允许您将人员分组。 一个人可以在许多组中,每个组可以有许多成员。

代表这些关系需要一个额外的表 - 也许这就是你的书真正说的? 在我刚给出的示例中,您将拥有一个Person表(id,名称,地址等)和一个Group表(id,组名等)。 两者都不包含有关谁在哪个组中的信息; 要做到这一点,你有第三个表(称之为PersonGroup),其中每个记录包含一个人员ID和一个组ID - 该记录代表人和组之间的关系。

需要找到一个组的成员? 您的查询可能如下所示(对于ID = 1的组):

SELECT Person.firstName, Person.lastName 
FROM Person JOIN PersonGroup JOIN Group 
ON (PersonGroup.GroupID = 1 AND PersonGroup.PersonID = Person.ID);

当然,MM关系确实存在于关系数据库中,并且它们还具有通过桥接表在某种程度上处理的能力,但是随着MM关系程度的增加,它也增加了复杂性,导致RW周期和延迟缓慢。 建议在关系数据库中避免这种复杂的MM关系。 图形数据库是最好的选择,擅长处理对象之间的多对多关系,这就是为什么社交网站使用Graph数据库处理用户和朋友,用户和事件等之间的MM关系的原因。

让我们在书籍和销售表之间发明一种虚构的关系(多对多的关系)。 假设您正在购买书籍,并且您购买的每本书都需要为该书生成发票编号。 还假设一本书的发票号可以代表对同一客户的多次销售(实际上不是,但我们假设)。 我们在书籍和销售实体之间存在多对多的关系。 现在,如果是这样的话,我们怎样才能获得有关1本书的信息,因为我们购买了3本书,因为理论上所有书籍都有相同的发票编号? 这引入了使用多对多关系的主要问题。 现在,如果我们在书籍和销售之间添加一个桥接实体,使得每本出售的图书只有1个发票编号,无论购买多少本书,我们仍然可以正确识别每本书。

在多对多关系中,存在明显的冗余以及插入,更新和删除异常,应通过桥接表将其转换为2个一对多关系来消除异常。

M:数据库设计中不应存在N个关系。 它们效率极低,不能用于功能数据库。 具有多对多关系的两个表(实体)(飞机,机场;教师,学生)不能都是彼此的孩子,没有交叉表就没有放置外键的位置。 飞机 - >飞机< - 机场; 老师< - 班 - >学生。

交叉表为依赖于其他两个表的实体提供了一个位置,例如,一个等级需要一个班级和一个学生,一个航班需要飞机和机场。 多对多关系隐藏数据。 交叉表显示此数据并创建一对多关系,可以更容易理解和使用 因此,问题出现了,飞机应该在什么桌子上 - 飞机或机场。 它们都不应该是交叉表中的外键,Flight。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM