什么是数据库中的一对多关系?

一对多关系是最常见的数据库关系之一。如果您想了解何时以及如何使用一对多关系,那么本文是一个很好的起点。

您肯定会使用一对多关系将信息存储在任何关系数据库中,无论您是在设计企业级软件还是只是创建一个简单的数据库来跟踪您叔叔的邮票收藏。

关系模型简介

关系数据库是任何现代事务应用程序的核心组件。关系模型由表(按行和列组织的数据)组成,这些表至少有一个标识每行的唯一键。每个表表示一个实体。以下示例显示了这一点,这是表示客户订单的表的非常简单版本:

什么是关系,我们为什么需要它们?

如果我们更深入地看一下前面示例中使用的表,我们将看到它并不真正表示完整的订单。它没有您期望它拥有的所有信息。您会注意到,它不包括与下订单的客户相关的任何数据,也没有关于订购的产品或服务的任何信息。

我们应该做些什么来完成这个设计来存储订单数据?我们是否应该将客户和产品信息添加到 Order 表中?这将需要为客户名称、税务标识符、地址等添加新列(属性),如下所示:

"Order ID""Order Date""Order Amount"Customer"Customer Address""Customer Phone""Tax Identifier"
1jun-23$10 248,15International Services Ltd1247 St River Blvd, Charlotte, NC(555) 478-8741IS789456
2jun-27$14 785,45World Master Importing Inc.354 Mountain Hill Rd, Los Angeles, CA(555) 774-8888WM321456
3jul-01$7 975,00First State Provisioning Llc444 North Highway, Houston, TX(555) 698-7411FS947561
4jul-03$6 784,25International Services Ltd1247 St River Blvd, Charlotte, NC(555) 478-8741IS789456
5jul-07$21 476,10World Master Importing Inc.354 Mountain Hill Rd, Los Angeles, CA(555) 774-8888WM321456
6jul-12$9 734,00First State Provisioning Llc444 North Highway, Houston, TX(555) 698-7411FS947561
7jul-17$14 747,45World Master Importing Inc.354 Mountain Hill Rd, Los Angeles, CA(555) 774-8888WM321456
8jul-21$19 674,85International Services Ltd1247 St River Blvd, Charlotte, NC(555) 478-8741IS789456

如果我们这样做,我们很快就会遇到问题。大多数客户下多个订单,因此此系统将存储客户信息多次,每个客户的每个订单一次。这似乎不是一个明智的举动。

此外,当客户更改其电话号码时会发生什么?如果有人需要给客户打电话,他们可能会在以前的订单上找到旧号码 - 除非有人用新信息更新数百(甚至数千)个现有订单。任何其他变化也是如此。

关系模型要求我们将每个实体定义为一个单独的表,并在它们之间建立关系。将所有信息存储在单个表中是行不通的。

表之间有几种类型的关系,但最常见的可能是一对多关系,通常写为 1:N。这种关系意味着表(通常称为父表)中的一行可以与另一个表(通常称为子表)中的许多行具有关系。一对多关系的一些常见示例如下:

  • 汽车制造商生产许多不同的车型,但特定的汽车型号仅由一家汽车制造商制造。
  • 一个客户可以进行多次购买,但每次购买都是由单个客户进行的。
  • 一家公司可以有多个电话号码,但一个电话号码属于一家公司。

表之间还有其他类型的关系;如果您想了解有关它们的更多信息,请参阅有关多对多关系的文章。

回到我们的初始订单示例,客户表将是父表,订单表是子表;一个客户可以有多个订单,而一个订单可以属于单个客户。

请注意,一对多定义允许父表中的一行与每个子表上的许多行相关联,但它不需要它。实际上,该设计允许客户拥有零订单(即尚未进行第一次购买的新客户),一个订单(已进行单次购买的相对较新的客户)或多个订单(频繁的客户)。

在 ER 图中显示一对多关系

让我们看一个更完整的示例,该示例使用 ER(或实体关系)图的简单客户订购系统。下面是模型: 

这是一个更逼真的设计。您会注意到图中有新的实体(表),该图现在包含“客户”、“订单”、“订单详细信息”和“产品”。但是,您注意到的最重要的事情是,表之间现在存在关系

在数据库模型中,关系由连接两个实体的线表示。这些关系的特征由不同的连接器表示:

  • 当存在一条垂直线时,离该连接线最近的实体只有一行受关系影响。它是一对多中的“一”。
  • 当存在看起来像鱼尾纹的多行连接器时,离该连接器最近的实体具有受关系影响的多行;它是“许多”。

查看图像并了解符号,很容易理解该图定义了每个订单可以有多个订单详细信息,并且每个订单详细信息属于单个订单

在表之间实现一对多关系

若要定义两个表之间的一对多关系,子表必须引用父表上的一行。定义它所需的步骤是:

  1. 向子表中添加一列,用于存储主标识符的值。(实际上,大多数数据库引擎都允许它是父表中的任何唯一键,而不仅仅是主键。根据您的业务需求,该列可以定义为强制性的;即便如此,通常也会创建外键列

注意:最好使引用列的名称与引用(父)表中的名称相同。这使得理解这种关系变得更加容易。

  1. 在子表上添加外键约束。这表示此新列中存储的每个值都引用父表上的一行。

  1. 向子表中添加行时,引用列的值必须与父表中的一个(且只有一个)值匹配。(这就是为什么必须引用构成主键或唯一键的列或一组列的原因)。
  2. 如果有人尝试从父表中删除某一行,或者尝试修改用作引用的唯一/主键的值,并且存在引用该行的子表,则操作将失败。

这两个功能可确保数据库保持其完整性。没有机会创建引用不存在的客户的订单,也没有机会删除已有订单的客户。

创建外键

外键语法通常取决于目标数据库引擎。定义逻辑模型后,可以使用“生成物理模型...”功能,将您的(与数据库无关的)模型转换为与您的数据库提供程序匹配的物理模型。Vertabelo 还将生成所需的 SQL 脚本,该脚本将允许您在目标数据库中创建表和关系。

1:N 关系的一些实际示例

现在,让我们回顾一下现实世界一对多关系的一些示例。

使用主键的一对多关系

这可能是定义一对多关系时最常见的方案。子表使用父表的主键值来建立关系。

此示例描述基本的联机流式处理服务。让我们回顾一下每个表中存储的内容,以及它们与模型中其他表的关系:

  1. 每个 ServiceType 定义帐户的“行为”方式(例如,如果帐户启用了 Full HD,则有多少用户可以同时连接到系统等)。它与其他实体有一个关系:
    • 帐户的一对多关系,这意味着每个服务类型可以有多个该类型的帐户。
  2. 每个帐户存储有关一个客户的信息。它与其他实体有两种直接关系:
    • 如上所述,每个帐户都属于一个服务类型
    • 此表与 Profile 表具有一对多关系,这意味着多个用户可以使用同一帐户连接到我们的系统。
  3. 每个配置文件代表我们系统中的一个用户。它与其他实体有两种关系:
    • 每个配置文件都属于一个帐户。这允许所有家庭成员(或一群朋友)共享同一个帐户,而每个人都有自己的个人属性(例如个人资料名称)。
    • 每个个人资料都有一个唯一的头像
  4. 每个头像都是一个图像,使我们能够快速识别每个帐户用户。它与另一个实体有一个关系:
    • 配置文件的一对多关系,这意味着可以将单个头像分配给不同帐户上的配置文件。

 

与自然或代理唯一键的一对多关系

代理主键的使用是一种被广泛接受的表建模方式。(代理主键由数据库生成,没有实际的业务价值。此方法生成的密钥更易于使用,并在需要更改时增加了一些灵活性。

但是,在某些情况下 - 例如,当我们需要与外部系统交互时 - 使用数据库中生成的密钥是一种糟糕的方法。对于这些方案,通常最好使用自然键,这些自然键是唯一值,是所存储实体的一部分,而不是由我们的数据库自动生成的。

以下示例表示组织的基本数据模型,该模型跟踪车辆(即汽车的品牌、型号、颜色和年份)、其所有者以及任何相关的运输违规行为。当我们定义它时,我们使用代理主键来建立车辆与品牌,车型和车主之间的关系,因为所有这些信息都由我们的系统内部处理。

在这个系统中,另一个城市的警察如何报告使用我们的车辆主键()非法停放的汽车?停放的车辆上不会自然提供此类信息,但车牌就在那里。这意味着从外部来源(在本例中为国家/地区的任何警察局)接收和关联信息的最简单方法是使用自然唯一密钥而不是代理主密钥。VehicleID

此处提供了此 SQL Server 逻辑关系图的物理实现:

 

同一表上的一对多关系

前面的示例重点介绍两个或多个表之间的关系,但也有一些情况是,同一表的行之间会出现这种关系。这种一对多关系也称为等级关系;它在许多系统中用于表示树状结构,即组织结构图,总帐科目或产品及其组成部分。

第一次需要创建这种结构时,您会忍不住为层次结构中的每个级别定义一个表,如下图所示:

 这种方法存在许多问题:

  • 所有表几乎完全相同,并存储相同的信息。
  • 如果您的组织添加新级别,则必须修改数据模型并添加新表、新外键等。
  • 如果员工获得晋升,您需要从一个表中删除他们,然后将其插入到另一个表中。

因此,对这种结构进行建模的最佳方法是使用引用自身的单个表,如下图所示:

 

在这里,我们看到一个 Employee 表和一个名为 的列。该列引用同一组织中作为当前员工的主管/经理的另一名员工。EmployeeID_Manager

我添加了后缀来区分当前行的 ID 和管理器的 ID。(我们可以改用,但我更喜欢保留引用列的原始名称,并且在两者位于同一表中的情况下,添加一个后缀来解释它实际具有的角色)。_ManagerManagerID

了解层次结构关系比其他一对多关系更复杂。但是,如果您忘记了存储所有信息的表,并想象实际上有不同的表,每个表都代表层次结构中的一个级别,则可视化起来会更容易一些。想象一下,您在两个实体之间建立关系,然后将它们组合成一个实体。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值