具有一对多关系的表的规范化
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_id
是Region
表的外键
我想知道 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_id
和 region_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 可以有多个键!以上是关于具有一对多关系的表的规范化的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot与Mybatis整合(包含generate自动生成代码工具,数据库表一对一,一对多,关联关系中间表的查询)