好吧,我希望我都记得正确,让我们开始吧……
Rules
让它们变得非常简短(并且不是很精确,只是为了让您初步了解它的全部内容):
-
NF1:表格单元格不得包含多个值。
-
NF2:NF1,加上所有非主键列必须依赖于所有主键列。
-
NF3:NF2,加上非主键列可能不会互相依赖。
指示
-
NF1:查找包含多个值的表格单元格,将它们放入单独的列中。
-
NF2:查找依赖于少于所有主键列的列,将它们放入另一个仅包含它们真正依赖的主键列的表中。
-
NF3:除了依赖于主键之外,还查找依赖于其他非主键列的列。将依赖列放入另一个表中。
Examples
NF1
一栏“state
” 具有诸如“WA, Washington”之类的值。NF1 被违反,因为它有两个值:缩写和名称。
解决方案:为了满足 NF1,创建两列,STATE_ABBREVIATION
and STATE_NAME
.
NF2
假设您有一个包含以下 4 列的表格,表示汽车型号的国际名称:
-
COUNTRY_ID
(数字,主键)
-
CAR_MODEL_ID
(数字,主键)
-
COUNTRY_NAME
(varchar)
-
CAR_MODEL_NAME
(varchar)
该表可能有以下两个数据行:
- 第 1 行:COUNTRY_ID=1、CAR_MODEL_ID=5、COUNTRY_NAME=美国、CAR_MODEL_NAME=福克斯
- 第 2 行:COUNTRY_ID=2、CAR_MODEL_ID=5、COUNTRY_NAME=德国、CAR_MODEL_NAME=Polo
也就是说,车型“Fox”在美国被称为“Fox”,但同一车型在德国被称为“Polo”(不记得这是否属实)。
NF2 被违反,因为国家名称不依赖于汽车型号 ID 和国家 ID,而仅依赖于国家 ID。
解决方案:要满足 NF2,请移动COUNTRY_NAME
到一个单独的表“COUNTRY”与列COUNTRY_ID
(主键)和COUNTRY_NAME
。要获取包含国家/地区名称的结果集,您需要使用 JOIN 连接两个表。
NF3
假设您有一个包含以下列的表,表示各州的气候条件:
-
STATE_ID
(varchar,主键)
-
CLIME_ID
(外键,气候带的 ID,如“沙漠”、“雨林”等)
-
IS_MOSTLY_DRY
(bool)
NF3 被违反,因为 IS_MOSTLY_DRY 仅取决于 CLIME_ID(至少让我们假设这一点),而不取决于 STATE_ID(主键)。
解决方案:要满足NF3,放置色谱柱MOSTLY_DRY
进入气候区表。
以下是关于练习中给出的实际表格的一些想法:
我应用上述 NF 规则,而不质疑主键列。但它们实际上没有意义,我们稍后会看到。
- NF1 没有被违反,每个单元格只保存一个值。
- EMP_NM 和所有电话号码违反了 NF2,因为所有这些列都不依赖于完整的主键。它们都依赖于 EMP_ID (PK),但不依赖于 DEPT_CD (PK)。我假设当员工调到另一个部门时,电话号码保持不变。
- DEPT_NM 也违反了 NF2,因为 DEPT_NM 不依赖于完整主键。它取决于DEPT_CD,但不取决于EMP_ID。
- 所有技能列也违反了 NF2,因为它们不是部门特定的,而是特定于员工的。
- SKILL_NM 违反了 NF3,因为技能名称仅取决于技能代码,而技能代码甚至不是复合主键的一部分。
- SKILL_YRS 违反了 NF3,因为它依赖于主键成员 (EMP_ID) 和非主键成员 (SKILL_CD)。因此它部分依赖于非主键属性。
因此,如果删除所有违反 NF2 或 NF3 的列,则仅保留主键(EMP_ID 和 DEPT_CD)。剩下的部分违反了给定的业务规则:这种结构将允许一名员工同时在多个部门工作。
让我们从远处回顾一下。您的数据模型涉及员工、部门、技能以及这些实体之间的关系。如果您对其进行规范化,您最终将得到一张用于员工的表(包含 DEPT_CD 作为外键),一个用于部门,一个用于技能,另一个用于员工和技能之间的关系,保存“技能”年”对于 EMP_ID 和 SKILL_CD 的每个元组(我的老师会称后者为“关联实体”)。