8.关系数据库设计——第三范式(3NF)
情况一:假定存在以下FD:position → salary
情况二:为了改善情况一,把( position,salary )单独做个 relation
规范化 Normalization
规范化是将 relation schema R 分解为片段(即较小的模式)R1, R2, R3, ......, Rn 的过程,即:分隔关系模式。目标是:
- 无损分解:存储的信息与之前的等价
- 依赖保留:FDs 存在于各个单 relation 中,不然验证一个 FD 要 join 多个 relations,耗时
- 好的格式:分解后的 relations 的冗余信息较少
无损分解
- 如果能利用分解后的表来恢复原来的表,则该分解是无损的,例如:
- 一般来说,当且仅当以下 FD 中至少有一个存在于 \(F^+\) 中时,将 R 分解为 R1 和 R2 才是无损的
- R1 ∩ R2 → R1
- R1 ∩ R2 → R2
- 即,两个 schema 的交集属性构成至少其中一个 schema 的 key。
有损分解的例子
将 R = ( A, B, C )分解为 R1 = ( A, B ) 和 R2 = ( B, C )
保留依赖分解
- 分解后的每个 relation schema Ri 的 FDs 记作 Fi
- 那么,当前仅当以下情况时,分解是保持依赖的
- 即所有子表格 FD 并集的闭包与原来表格 FD 闭包一致
非保持依赖分解的例子
- R 中存在 FD :B → C,由于 B 不是该表的 key,B 和 C 出现存储冗余信息
- 为什么这是一个有损分解
- 因为:F1 = { { A } → { B } }, F2 = { { A } → { C } } 且 ( F1 ∩ F2 )+ ≠ F+. 我们丢失了 { B } → { C }.
保持依赖分解的例子
- 该分解是无损的,因为
- F1 = { { A } → { B } }, F2 = { { B } → { C } } 且 ( F1 → F2 )+ = F+
寻找好的 schema 设计 & 第一范式 1NF
一个好的 schema 设计:
- 无损分解,确保正确性
- 依赖关系保存,不是必需的,但是向往的
- 良好的形式,不是必需的,但是向往的
为此,我们定义:
- 如果表中所有属性的域仅包含 atomic values (没有多值属性),则该表是第一范式(1 NF)。也就是说该表没有多值属性
- 根据关系模型的定义,关系表总是符合第一范式的
- 关系表的设计只满足 1NF 显然是不够的。为此,我们定义以下规范标准
- 2NF
- 3NF
- BCNF
- 特别的,对于 3NF 和 BCNF,我们还将介绍在 schema 不满足这些性质时,如何将其分解,使其满足性质
第二范式 2NF
- 定义 R 为一个关系模式,其 FD 为 F
- R 符合第二范式( 2NF )当且仅当:
- 主属性的定义:该属性被某个候选键所包含
- 2NF :防止候选键的真子集决定非主属性
- 例子:
- 考虑关系表 { A, B, C, D } 以及它的 FDs :
- { A, B } 是候选键,而{ A }是候选键{ A, B }的子集,{ D }不是主属性
- 由上推出:由于 { A } → { D }存在,这个表不符合主属性
- 考虑关系表 { A, B, C, D } 以及它的 FDs :
- 总结:非主属性必须完全依赖于候选码(在 1NF 基础上消除非主属性对主码的部分函数依赖)
- 实际的例子
- 以一个订单为例,主键为订单号和商品号
- 我们可以看到商品名称这个属性仅仅与商品编号相关,也就是仅仅依赖于主键的一部分。这就违背了第二范式中“其他属性必须完全依赖于主键”的规则,因此需要将该属性分离到商品信息表中
- 以一个订单为例,主键为订单号和商品号
第三范式 3NF
- 定义 R 为一个关系模式,其 FD 为 F
- R 符合第三范式仅当
- 即:对于每一个 non-trivial FD:
- 左侧是 key,或者
- 右侧是主属性(候选键的一部分)
- 总结:第三范式就是防止非键决定非主属性
- 例子:
- 如上面这张表,很明显这里的城市人口、特色等属性都仅仅依赖于用户所在的城市,而不是用户,只能算间接的关系。因此最好的做法是将城市相关的属性分离到一个城市信息表中
- 第三范式例子
- 没有任何 FD 违反 3NF 规则。因此,R 属于 3NF
第三范式分解
该分解一定满足:
-
无损分解,确保正确性
-
依赖关系保存,不是必需的,但是向往的
-
良好的形式,不是必需的,但是向往的
-
例子:
- 候选键为:{ customer-name, branch-name } or { customer-name, banker-name }.
- { banker-name } → { office-number } 违背了第三范式
- 3NF 分解:
- 对于每个规范覆盖(也就是 1 和 2 )创建一个表
- Customer-Branch 有 candidate key,算法终止。
- 对于每个规范覆盖(也就是 1 和 2 )创建一个表
-
第三范式的冗余(不足)
-
符合第三范式的表仍有缺陷
- 冗余:例如我们重复了 Au 在 SYSU branch 工作的信息
- 需要分配 null 属性。例如,陈先生在中心区工作,尽管他没有被分配任何客户