为什么没有多对多关系?

时间:2011-09-07 19:01:13

标签: sql database

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

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

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

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

谢谢!

11 个答案:

答案 0 :(得分:44)

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

答案 1 :(得分:5)

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

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

答案 2 :(得分:3)

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

像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
希望有所帮助。

答案 3 :(得分:2)

  
    

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

  

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

  
    

我没有找到解释为什么要避免多对多关系的具体原因(或更好的例子),

  

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

答案 4 :(得分:1)

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

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

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

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

答案 5 :(得分:1)

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

这些关系的表示需要一个额外的表 - 也许这就是你的书真正说的?在我刚给出的示例中,您将拥有一个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);

答案 6 :(得分:1)

这是对的。多对多关系分为几个一对多关系。所以基本上,存在很多很多关系!

答案 7 :(得分:0)

当然,M-M关系确实存在于关系数据库中,它们也具有通过桥接表在某种程度上进行处理的能力,但是,随着M-M关系程度的增加,它也增加了复杂度,从而导致较慢的R-W周期和等待时间。 建议在关系数据库中避免这种复杂的M-M关系。图数据库是最好的选择,并且擅长处理对象之间的多对多关系,这就是为什么社交网站使用图数据库来处理用户与朋友,用户和事件等之间的M-M关系。

答案 8 :(得分:0)

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

答案 9 :(得分:0)

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

答案 10 :(得分:-1)

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

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