一对多和多对一关系的区别

162

1
这是完美的解释:http://en.wikipedia.org/wiki/Many-to-many_(data_model)。 - RobertPitt
@RobertPitt,多对多文章与问题有何关联?您可能更想指的是https://en.wikipedia.org/wiki/One-to-many_(data_model)。 - TMG
15个回答

148

是的,情况相反也一样。这取决于实体在关系的哪一侧。



例如,如果一个部门可以雇用多名员工,则部门到员工是一对多关系(1个部门雇用多名员工),而员工到部门的关系是多对一(多名员工在一个部门工作)。

更多关于关系类型的信息:

数据库关系 - IBM DB2文档


3
我担心这没有意义!我认为这个顺序表示依赖关系!比如,用户到角色可能是一对多的,但不是多对一的,因为一个人无法获取使用该角色的用户的引用!这样说有意义吗? - Amanuel Nega
也许现在可以考虑数据库关系了? - fragorl
1
但是如果一个员工只能在一个部门工作呢?嗯?这就没有多对一的情况了。 - Jin Lim
这是正确的,但我认为它需要进一步的解释和技术上的证明。开发人员必须理解RDBMS与ORM和对象关系型数据库管理系统之间的区别。请看我的回答。 - Athanassios

41

从这篇关于数据库术语的页面中:

表之间的大多数关系都是一对多。

例如:

  • 一个区域可以是许多读者的栖息地。
  • 一个读者可以有很多订阅。
  • 一家报社可以有很多订阅。

多对一关系与一对多关系相同,但是从不同的视角看待。

  • 许多读者住在同一个区域。
  • 许多订阅可能属于同一个读者。
  • 许多订阅都是为同一家报纸的。

29
“一对多”和“多对一”关系有什么真正的区别?
这些术语之间有概念上的差异,可以帮助您可视化数据,并且可能存在生成的模式中应该充分理解的差异。但大多数情况下,区别只是从不同角度看问题。
在“一对多”关系中,本地表具有一个与另一个表中的多个行相关联的行。在SQL for beginners的示例中,一个“客户”可以与多个“订单”相关联。
在相反的“多对一”关系中,本地表可以有许多与另一个表中的一行相关联的行。在我们的示例中,许多“订单”可以与一个“客户”相关联。这种概念上的差异对于心理表征非常重要。
此外,支持关系的模式在“客户”和“订单”表中可能会以不同的方式表示。例如,如果客户具有列“id”和“name”:
id,name
1,Bill Smith
2,Jim Kenshaw

如果要将一个订单与一个客户关联,许多SQL实现会在订单表中添加一列来存储关联的客户id(在此模式中为customer_id):

id,date,amount,customer_id
10,20160620,12.34,1
11,20160620,7.58,1
12,20160621,158.01,2

在上述数据行中,如果我们查看customer_id id列,我们会发现Bill Smith(客户编号#1)有两个与之关联的订单:一个金额为$12.34,另一个金额为$7.58。而Jim Kenshaw(客户编号#2)只有一笔金额为$158.01的订单。
需要注意的是,通常一对多关系实际上不会向作为“一”的表中添加任何列。 Customer没有描述与Order关系的额外列。事实上,Customer可能还与ShippingAddressSalesCall表存在一对多的关系,但Customer表中没有添加额外的列。
然而,为了描述多对一的关系,通常会在“多”表中添加一个id列,该列是指向“一”表的外键 - 在本例中,将customer_id列添加到Order中。要将订单#10(价格为12.34美元)与Bill Smith相关联,我们将customer_id列分配给Bill Smith的id 1。

但是,也有可能存在另一个描述Customer和Order关系的表,因此不需要向Order表添加其他字段。可以有一个名为Customer_Order的表,其中包含Customer和Order的键。

customer_id,order_id
1,10
1,11
2,12

在这种情况下,一对多多对一都是概念上的,因为它们之间没有模式更改。具体机制取决于您的模式和SQL实现。
希望这可以帮到您。

4
一般情况下被称为包含依赖。外键约束是最常见的包含依赖类型,但并非所有包含依赖都涉及外键。共同的属性或属性集(“参照属性”)在两个表中都存在。在“一”的一边,这些属性被称为候选键。在“多”的一边,它们可能是外键。术语“一对多”或“多对一”可适用于任何涉及至少一个候选键的包含依赖,而不必暗示哪一边可能是可选的。 - nvogel
2
这个问题是关于关系型数据库和SQL,而不是Java。也许你对Java是正确的。 - nvogel
2
我想说的是,这两种描述方式实际上是在不同的角度下描述同一种关系。就像“A是B的子集”和“B是A的超集”意思是相同的。 - nvogel
Gray,对我来说,最后两段读起来是一样的。你如何实现“多对一”?我记得你说过它会向“一”的一侧添加列…… - Alexander Suraphel
我已经修改了我的回答@AlexanderSuraphel。id列通常添加到“many”表中。id引用(指向)“one”表。 - Gray
显示剩余5条评论

13

SQL

拥有一个关系的两个表格

在SQL中,只有一种类型的关系,被称为引用。 (您的前端可能会执行有用或令人困惑的操作 [例如在某些答案中],但这是另一回事。)

  • 一个表格中的外键(指向其他表格中的主键)
    被称为参考

  • 在SQL术语中,Bar引用Foo
    而不是反过来

    CREATE TABLE Foo (
        Foo   CHAR(10)  NOT NULL, -- primary key
        Name  CHAR(30)  NOT NULL
        CONSTRAINT PK             -- constraint name
            PRIMARY KEY (Foo)     -- pk
        )  
    CREATE TABLE Bar (
        Bar   CHAR(10)  NOT NULL, -- primary key
        Foo   CHAR(10)  NOT NULL, -- foreign key to Foo
        Name  CHAR(30)  NOT NULL
        CONSTRAINT PK                -- constraint name
            PRIMARY KEY (Bar),       -- pk
        CONSTRAINT Foo_HasMany_Bars  -- constraint name
            FOREIGN KEY   (Foo)      -- fk in (this) referencing table
            REFERENCES Foo(Foo)      -- pk in referenced table
        )
    
  • 由于Foo.Foo是主键,它是唯一的,对于任何给定的Foo值,只有一行。

  • 由于Bar.Foo是一个参考、外键,并且没有唯一索引,因此对于任何给定的Foo值,可能有多个行。

  • 因此关系Foo::Bar是一对多的。

  • 现在你可以从另一个角度观察这种关系,Bar::Foo是多对一的。

    • 但是不要让这使你困惑:对于任何一个Bar行,它只引用了一个Foo行。
  • 在SQL中,这就是我们所拥有的。这就是所有必需的。

一对多和多对一关系之间的真正区别是什么?

只有一个关系,因此不存在区别。从一个“端点”或另一个“端点”感知(观察),或者倒过来读,都不会改变这种关系。

基数

基数首先在数据模型中声明,这意味着逻辑和物理(意图),然后在实现中(实现的意图)。

Cardinality

一对零或多个
在SQL中,这就是所需的(如上所述)。

一对一对多
您需要一个事务来强制执行引用表中的“一”。

一对零或一
您需要在Bar中:

CONSTRAINT AK    -- constraint name
    UNIQUE (Foo) -- unique column, which makes it an Alternate Key

一对一
你需要一个事务来强制Referencing表中的一对一。

多对多

在物理层面上不存在这样的东西(请注意,SQL中只有一种类型的关系)。

在建模练习的早期逻辑层面上,画这样的关系是方便的。在模型接近实现之前,最好使用只能存在的东西来升华它。这样的关系通过在物理[DDL]层面上实现一个联结表来解决。

Many-to-many Resolved


1
@Martijn Peters。我可以编辑它以符合行为准则。但是您还删除了(a)解释和(b)现实中的事实证据。我该怎么办? - PerformanceDBA
3
请用其他方式表达这些内容,而不是诉苦、辱骂或诋毁任何人的智商或职业操守。关注技术本身,而不是可能对错的人。 - Martijn Pieters

6

没有区别,只是语言和个人偏好的问题,关系的表述方式不同而已。


2
确实存在差异,无论是概念上还是生成的模式上。请参见我的答案:https://dev59.com/YW445IYBdhLWcg3w_PAn#37954280 - Gray
6
没有。你的回答不仅是错误的,而且会让初学者(提出这个问题的人)感到困惑。 - PerformanceDBA

5
一对多和多对一在Multiplicity方面相似,但不同在Aspect(即方向性)。实体类之间的关联和表格之间的关系映射。有两类关系: 1. Multiplicity(ER术语:基数) - 一对一关系(缩写为1:1):例如丈夫和妻子 - 一对多关系(缩写为1:N):例如母亲和孩子 - 多对多关系(缩写为M:N):例如学生和科目 2. Directionality:不影响映射,但会影响我们如何访问数据。 - 单向关系:一个关系字段或属性引用另一个实体。 - 双向关系:每个实体都有一个关系字段或属性引用另一个实体。

1
关系型数据库中没有“方向性”。每个关系都有两个“端点”:引用(被引用的表)和引用者(进行引用的表)。SQL/DML允许任何表以任何你想要的方式被引用,一侧、另一侧、两侧或无侧。 - PerformanceDBA
@PerformaceDBA - 如果关系具有外键约束,则存在方向性。 - Jason210
@Jason210 1) 在SQL DDL中,要建立关系,必须指定FOREIGN KEY约束。因此,所有关系都是FK约束。2)这是在物理DDL级别上,忽略了逻辑(这是问题所在)。关系模型是逻辑的。从逻辑上看,在编写SQL DML时,关系有两个“端点”,不限于DDL声明的内容。 - PerformanceDBA
请查看以下网址以获取更多有关编程的信息:https://www.relationaldbdesign.com/database-design/module6/three-relationship-types.php - Premraj

4

你第一个问题的答案是:两者相似。

你第二个问题的答案是:一对多--> 一个男人(男人表)可以有多个妻子(女人表),多对一--> 多个女人已经嫁给了一个男人。

现在,如果你想将这种关系与 MAN 和 WOMEN 两个表关联起来,那么 MAN 表的一行可能与 WOMEN 表中的多行有多个关系。希望这样清楚明白。


2
被踩了,你应该提供一个比多夫制更合适的例子。 - toong

2
这是一个很好的问题,根据我的经验,在ERD图和关系数据库中,方向是隐含的。在RDBMS中,您总是定义多对一(平凡情况下的一对一)的关系。关系的多侧,也就是子代,引用了关系的一侧,也就是父代,并使用外键约束来实现这一点。严格地说,您必须访问索引,获取一侧的主键记录,然后访问该记录以获取更多信息。
除非我们谈论的是面向对象的关系型数据库管理系统,例如Postgres、Intersystems Cache等,否则您不能反过来做。这些DBMS允许您在两个实体(表)之间定义双向关系。在这种情况下,通过使用引用(子代)数组来实现从另一个方向访问记录,即一对多。在ORM中,您有相互引用的类,方式与我们在此处描述的方式相同。
警告:IT市场上大多数RDBMS在严格意义上不是关系数据库管理系统,考虑到空值、重复记录等,其中许多允许的功能都违反了关系的定义。

商业关系型数据库管理系统 SQL 平台(除了 Oracle)都是关系型的。免费软件则不是关系型的(允许禁止的对象,如循环引用),也不符合 SQL 标准 - PerformanceDBA

0

实际上没有什么区别。只需根据您看待问题的方式使用最合理的关系,就像Devendra所示。


3
没有,你的答案不仅是错误的,而且会让初学者(提出这个问题的人)感到困惑。 - PerformanceDBA

0

一对多和多对一关系是指同一逻辑关系,例如一个所有者可能拥有多个房屋,但一个房屋只能有一个所有者。

因此,在这个例子中,所有者是“一”,而房屋是“多”。 每个房屋都有一个owner_id(例如外键)作为额外的列。

这两者之间实现的区别在于哪个表定义了关系。 在一对多中,所有者是定义关系的地方。例如,owner1.homes列出了所有带有owner1的owner_id的房屋。 在多对一中,房屋是定义关系的地方。例如,home1.owner列出了owner1的owner_id。

我实际上不知道在什么情况下会实现多对一的安排,因为它似乎有点多余,因为您已经知道owner_id。也许与删除和更改的清洁度有关。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接