具有一对多关系的表的规范化

Posted

技术标签:

【中文标题】具有一对多关系的表的规范化【英文标题】:Normalization of a table with a one-to-many relation 【发布时间】:2016-10-27 09:35:39 【问题描述】:

如果 city 和 region 之间存在关系,其中 region -> city 是一对多映射。

以下是数据库设计:

城市

    city_id 城市名称 region_id

地区

    身份证 姓名

region_idRegion 表的外键

我想知道 region_id 和 city_id 是否是候选键。由于 city_name 对候选键的部分依赖,关系不在 2 NF 中。

如何处理一对多映射的规范化?

【问题讨论】:

如果 city_id 是一个自动增量 ID(你应该明确地清除它,但除非这是某种家庭作业问题,否则它应该是一个自动增量 ID,以免你的表格太复杂),@ 987654324@ 是city 的(唯一)候选键(尽管(city_name, region_id) 也可能是一个,取决于您的区域有多大,但我认为这没有多大逻辑意义)并且您的表排在第 5 位正常形式。 【参考方案1】:

由于 city_name 对候选键的部分依赖,关系不在 2 NF 中

那么你的数据是这样的吗?:

Region ( key = region_id ):
 region_id = 'R01', region_name = 'France' ;
 region_id = 'R02', region_name = 'Texas' ;

City ( key = ??? ):
 city_id = 'C01', city_name = 'Paris', region_id = 'R01' ;  -- Paris, France
 city_id = 'C01', city_name = 'Paris', region_id = 'R02' ;  -- Paris, Texas

换句话说,您只想要一个名为“巴黎”的城市,因为所有巴黎人都是同一个实体?我认为这是一种奇怪的世界观!

我认为大多数人会认为每个巴黎都是独立的实体,因此会有不同的标识符来区分它们:

Region ( key = region_id ):
 region_id = 'R01', region_name = 'France' ;
 region_id = 'R02', region_name = 'Texas' ;

City ( key = ??? ):
 city_id = 'C01', city_name = 'Paris', region_id = 'R01' ;
 city_id = 'C02', city_name = 'Paris', region_id = 'R02' ;

即使有上面​​的表格,我也对城市的钥匙有点不清楚。我认为关系变量“做得太多”;理想情况下,我们应该有第二个 relvar 来模拟城市与其区域之间的关系:

Region ( key = region_id ):
 region_id = 'R01', region_name = 'France' ;
 region_id = 'R02', region_name = 'Texas' ;

City ( key = city_id ):
 city_id = 'C01', city_name = 'Paris' ;
 city_id = 'C02', city_name = 'Paris' ;

CityRegion ( key = city_id ):
 city_id = 'C01', region_id = 'R01' ;
 city_id = 'C02', region_id = 'R02' ;

以上内容现已完全标准化(实际上在 6NF 中)。

【讨论】:

在 1:n 关系中,不需要单独的表格连接城市和地区。有关系表的解释太科学了,与实用性无关。【参考方案2】:

city_idregion_id 字段的组合可以是 city 中的候选键,具体取决于您如何定义这两个字段(您的帖子没有说明),因为

候选键可以是可以作为数据库中唯一键的任何列或列组合。一张表中可以有多个候选键。每个候选键都可以作为主键。

来源:Difference Between Candidate Keys and Primary Key In Simple Words

您可以将 city_id 单独定义为唯一的(可能是 auto_increment),但您也可以仅定义 2 个字段的组合唯一。

但是,我不会做后者,因为如果您重新分类一个城市(从一个地区移动到另一个地区),那么您可能还必须更改 city_id 组件。

【讨论】:

如果我将一个城市从区域 1 移动到区域 2,我没有得到最后一点,那么只有城市的 region_id 会改变,为什么 city_id 会改变 如果您使用 city_id 和 region_id 的组合作为您的 PK,那么您可能有 2 条记录,其中 city_id - region_id 组合为 (1,1) - (1,2)。现在,如果要将城市 (1,1) 移动到区域 2,则不能简单地将 region_id 更改为 2,因为您已经有了城市 (1,2)。在这种情况下,您还需要更改 city_id 并获得 (2,2)。 这意味着保持城市ID作为主键将使其在2 nf中 是的,因为那样城市名称将在功能上完全依赖于 PK,这就是重点。 我不认为链接的文章太多。关系理论很久以前就远离了“主”键的概念(注意 OP 也没有提到“主”?),而文章建议您确定候选键,选择一个作为“主”(基于可疑的标准) IMO)然后删除所有候选键,即我认为作者不认为 relvar 可以有多个键!

以上是关于具有一对多关系的表的规范化的主要内容,如果未能解决你的问题,请参考以下文章

如何将具有一对多关系的表组合成 1 行记录

在实体框架中加入 3 个一对多表

Eloquent中一对多关系表的分组和总和

Hibernate映射关系:一对一对多和多对多

SpringBoot与Mybatis整合(包含generate自动生成代码工具,数据库表一对一,一对多,关联关系中间表的查询)

在 ORM(Eloquent)中,具有 Genre 的 Book 是一对多关系吗?