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


117

一对多和多对一关系的真正区别是什么?它只是反向的,是什么样的?

除了本主题之外,我没有找到关于此主题的任何“好理解”教程:初学者使用的SQL:第3部分-数据库关系



@RobertPitt多对多文章与该问题有什么关系?您可能更想说en.wikipedia.org/wiki/一对多(data_model)
TMG

Answers:


111

是的,反之亦然。它取决于实体存在于关系的哪一侧。

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

有关关系类型的更多信息

数据库关系-IBM DB2文档


2
恐怕没有场面!(但不能确定)我认为顺序代表依赖性!不是吗?EG,一个角色用户可能是一对多,但不是一对多,因为一个人无法获得使用该角色的用户的引用!那有意义吗?
阿曼纽尔·涅加,2014年

也许现在是数据库关系
fragorl

29

从此页面开始有关数据库术语

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

例:

  • 一个地区可以成为许多读者的栖息地。
  • 一个读者可以有许多订阅。
  • 一份报纸可以有很多订阅。

一对多关系与一对多关系相同,但是观点不同。

  • 许多读者住在一个地区。
  • 许多订阅可以是同一读者。
  • 许多订阅是针对同一份报纸。

20

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

这些术语之间存在概念上的差异,应该可以帮助您可视化数据,并且所生成的架构中的可能存在的差异也应该被完全理解。通常,差异是透视图之一。

一对多关系中,本地表具有一行,该行可能与另一表中的许多行相关联。在SQL的初学者示例中,一个Customer可能与许多Order s。

在相反的多对一关系中,本地表可能具有与另一表中的一行关联的许多行。在我们的示例中,许多Order可能与一个Customer。这种概念上的差异对于心理表征很重要。

此外,可以在CustomerOrder表中以不同方式表示支持该关系的架构。例如,如果客户具有列idname

id,name
1,Bill Smith
2,Jim Kenshaw

然后,要使a Order与a关联Customer,许多SQL实现会在Order表中添加一列,该列存储id关联的的列Customer(在此架构中customer_id

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

在上面的数据行中,如果我们查看customer_idid列,我们看到Bill Smith(customer-id#1)有2个与他相关的订单:一个订单价格为$ 12.34,一个订单价格为$ 7.58。 Jim Kenshaw(客户ID#2)只有1个订单,价格为$ 158.01。

重要的是要意识到,通常一对多关系实际上并未向表中添加任何为“一个”的列。的Customer没有多余的列描述与的关系Order。实际上,它们Customer可能与ShippingAddressSalesCall表也具有一对多的关系,但是没有向Customer表中添加其他列。

但是,对于要描述的多对一关系,通常将一id列添加到“许多”表中,该列是“一个”表的外键-在这种情况下,将customer_id列添加到中Order。对于关联的订单10(价格为$ 12.34)Bill Smith,我们将customer_id列分配给Bill SmithID为1。

但是,也可能有另一个表描述Customerand Order关系,因此无需在该Order表中添加其他字段。不是添加的customer_id字段的Order表,可能有Customer_Order表,其中包含两个按键CustomerOrder

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

在这种情况下,一对多多对一都是概念性的,因为它们之间没有架构更改。哪种机制取决于您的架构和SQL实现。

希望这可以帮助。


3
一般情况称为包含依赖关系。外键约束是包含依赖项的最常见类型,但并非所有包含依赖项都涉及外键。两个表中始终存在一个或多个公共属性(“引用”)。在“一个”方面,这些属性称为候选键。在“许多”方面,它们可能是外键。术语“一对多”或“多对一”可以应用于涉及至少一个候选密钥的任何包含依赖性,而不必暗示哪一侧是可选的。
nvogel

有趣的@sqlvogel。在Java中,javax.persistence.OneToMany与Java 不同ManyToOne。您是说它们是同义词,还是仅取决于实现?我的答案不正确吗?
灰色,

2
问题是关系数据库和SQL,而不是Java。也许您对Java是正确的。
nvogel '16

我以@sqlvogel为例。您是说“一对多”和“一对多”是同义词吗?
格雷

2
我是说,这是描述完全相同的关系但从不同角度描述的两种方法。以同样的方式,“ A是B的子集”意味着与“ B是A的超集”相同。
nvogel


4

您第一个问题的答案是:两者相似,

您的第二个问题的答案是:一对多->一个MAN(MAN桌子)可能有多个妻子(WOMEN桌子)多对一->超过一个女人已与一个MAN结婚。

现在,如果要将此关系与两个表MAN和WOMEN相关联,则一个MAN表行可能与WOMEN表中的行有很多关系。希望清楚。


3

具有一个关系的两个表

的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中,这就是我们所拥有的。那就是所有必要的。

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

只有一种关系,因此没有区别。感知(从一个“端点”或另一个“端点”)或向后读取它不会更改关系。

基数

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

基数

一对多
零到多)在SQL中,(以上所述)全部是必需的。

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

一对一到零比一,
您需要Bar

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

一对一
您需要一个事务来强制引用表中的一个事务

多对多
在物理级别上没有这样的东西(回想一下,SQL中只有一种类型的关系)。

在建模练习的早期逻辑级别,可以方便地绘制这种关系。在模型接近实现之前,最好将其提升为仅使用可以存在的事物。通过实现关联表可以解决这种关系。

多对多解决


1
@马丁·彼得斯(Martijn Peters)。我可以对其进行编辑以符合行为准则。但是,您还删除了(a)解释和(b)事实证据。我该怎么办?
PerformanceDBA

3
寻找一种不同的方式来表达这些东西,而不必诉诸于任何人的智力或专业行为上的骂,称呼和撒谎。专注于技术,而不是那些可能错不对的人。
马丁·彼得斯

2

一对多和多对一在多重性上相似,但在长宽比(即方向性)上却不相似。

的映射关联实体类和之间的关系的表之间。有两类关系:

  1. 多重性(ER术语:基数)
    • 一对一关系:丈夫和妻子的例子
    • 一对多关系:示例母亲和孩子
    • 多对多关系:示例学生和学科
  2. 方向性:不影响映射,但会影响我们访问数据的方式。
    • 单向关系:引用另一个实体的关系字段或属性。
    • 双向关系:每个实体都有一个关系字段或属性,该字段或属性引用了另一个实体。

关系数据库中没有“方向性”。每个关系都有两个“终点”:引用(被引用的表)和引用(进行引用的表)。SQL / DML允许您以任何方式引用任何表...一侧...另一侧...两侧...无侧。
PerformanceDBA

0

没有实际的区别。就像使用Devendra所说明的那样,只要使用最有意义的关系即可。


在概念上和生成的模式上肯定都存在差异。看到我的答案:stackoverflow.com/a/37954280/179850
灰色

3
@灰色。不,那里没有。您的答案不仅不正确,还会使初学者(问这个问题的人)感到困惑。
PerformanceDBA

0
  • ---一对多-父母可以生两个或两个以上的孩子。
  • ---一对多---那三个孩子可以有一个单亲。

    两者是相似的。可以根据需要使用。如果您想为特定的父母找到孩子,那么您可以选择一对多。否则,想寻找双胞胎的父母,可以选择多对一。同样....,


-6

一对多父类包含n个孩子,因此它是一个集合映射。

多对一的 n个孩子包含一个父对象,因此它是对象映射


这个答案很好,并且有其他信息不明白为什么它被否决了。在单向上下文中,一对一,一对多将无法提供相同的代码质量,具体取决于UX:如果需要获取一组相关的数据所以一对多是比较明智​​的,因为您不需要在条件适合的select语句中,因为该条件在映射中存在,但是如果用户不需要获取数据集并且对每一行都感兴趣则将它作为唯一理想的实例,因此多对一是明智的选择
Mohammed Housseyn Taleb

可能是一个很好的答案,但它们却不尽相同:多对一的父类包含n个孩子,一对多的父子对一个孩子有很多。在SQL中,由于多对一关系可以是全向的,所以可能没有什么区别,但是在诸如Django之类的框架中,这是一个主要问题,因为没有一对多的关系,并且没有外键处理多对一关系只能自然地在一个方向上进行,而不能以相同的方式在另一方向上使用。
iFunction
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.