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

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

以下是数据库设计:

城市

  1. city_id
  2. 城市名称
  3. region_id

地区

  1. 身份证
  2. 姓名

region_idRegion 表的外键

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

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

【问题讨论】:

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

标签: mysql sql


【解决方案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 可以有多个键!
猜你喜欢
  • 2023-03-03
  • 2013-04-19
  • 2015-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-29
  • 2017-08-19
相关资源
最近更新 更多