banner
NEWS LETTER

7. 范式设计

Scroll down

第一部分:为什么要瞎折腾?(动机)

场景:如果不设计,直接把所有数据(老师、系别、楼、预算)塞进一张大表 inst_dept ,这就是个坏设计

三大痛点 (Pitfalls)

  1. 数据冗余 (Redundancy):物理系有100个老师,“物理系-Watson楼-预算9万”这条信息就要重复存100遍。

  2. 更新异常 (Update Anomaly):物理系搬家了?你必须修改那100行数据。漏改一行,数据就打架了(不一致)。

  3. 插入异常 (Incompleteness):新成立了“数学系”但还没招到老师(主键为空),结果这个系的信息连存都存不进去。

目标:把大表拆成小表(分解),消除冗余,同时保证数据不丢、逻辑不乱。


第二部分:拆表的工具——函数依赖 (FD)

定义:数据之间的逻辑绑定关系,记作

  • 含义:只要知道了 的值,就能唯一确定 的值(就像知道了“身份证号”就能确定“姓名”)。

1. 三种需要消灭的“坏依赖”

类型 说明 通俗理解
平凡依赖 (Trivial) (如 ID, Name ID) 废话。这不需要处理。
部分依赖 (Partial) ,但 只依赖 的一部分 “抱半条大腿”。主键是(A+B),C只依赖A。
传递依赖 (Transitive) ,导致 “隔山打牛”。老师定系,系定楼。老师跟楼的关系是隔了一层的。

2. 核心计算:闭包 (Closure)

  • (规则闭包):基于现有规则能推导出的所有规则。

  • (属性闭包):给定属性 ,它能决定的所有其他属性。

  • 考点:如果 (全表属性),那 就是超键 (Superkey)

3. 正则覆盖 (Canonical Cover ) —— 难点与计算核心

这是进行 3NF 分解 (Synthesis Algorithm) 的第一步,必须掌握。

3.1 动机与定义

  • 目的:找到一个“最小、最精简”的函数依赖集 ,它和原来的 逻辑等价(即闭包相同),但去掉了所有多余的废话。

  • 要求

    1. 等价性 互相推导。

    2. 右侧单属性 必须拆成

    3. 无多余属性:左边或右边没有任何属性是多余的。

3.2 判定“多余” (Extraneous Attributes)

  • 左侧多余 (Left side)

    • 对于 ,如果 本身就成立(即 ),那么 就是多余的。
  • 右侧多余 (Right side) / 规则冗余

    • 对于 ,如果删掉这条规则,利用剩下的规则还能推出 ,则它是废话。

3.3 计算步骤 (Algorithm)

请严格按照以下步骤操作,不要跳步:

  1. Flatten (拆分右侧)

    • 将所有右边包含多个属性的依赖拆开。例: 变为
  2. Remove Extraneous (L) (去左侧多余)

    • 检查左边有多个属性的规则(如 )。试着去掉其中一个属性,用 计算剩余属性的闭包,看能否推出右边。
  3. Remove Redundant Rules (R) (去冗余规则)

    • 逐条检查:如果删掉这条规则,利用剩下的规则能否将其推导出来?(通常是因为传递性 )。

📝 实战例题

题目:。求

解:

  1. 拆分

  2. 去左侧多余:检查 。因为 ,所以 多余。规则简化为

    • 当前集合:(去重后)。
  3. 去冗余规则:检查 。因为 可以推导出

    • 结论: 是废话,删掉。

      最终结果:


第三部分:好设计的标准——范式 (Normal Forms)

我们像爬楼梯一样,等级越高,要求越严。

  1. 第一范式 (1NF)

    • 要求格子不能混装。属性必须是原子的(Atomic)。

    • 例子:电话号码栏不能填“138xxx, 139xxx”,必须拆成两条记录。

  2. 第二范式 (2NF)

    • 要求:满足 1NF + 非主属性完全依赖于候选键

    • 消灭对象部分依赖

    • 人话:如果你有两个老板(组合主键),你不能只听其中一个人的话。

  3. 第三范式 (3NF)

    • 要求:满足 2NF + 非主属性不传递依赖于候选键

    • 消灭对象传递依赖

    • 人话:非主键字段之间不能互相打架(互相决定)。

    • 宽松条款:在 中,如果 B 是候选键的一部分(主属性),3NF 是允许的。

  4. BCNF (Boyce-Codd范式)

    • 要求:所有非平凡依赖 中, 必须是超键

    • 人话想管事?先当老大。任何决定别人的字段,自己必须是全表的唯一标识。


第四部分:怎么拆?—— 分解算法 (Decomposition)

如果表设计不好,我们要把它拆解(Decomposition)。

两大原则:

  1. 无损连接 (Lossless-join)必须满足。拆开的表拼回去,数据不能多也不能少。

  2. 保持依赖 (Dependency Preservation)尽量满足。拆分后,规则不丢。

算法一:BCNF 分解算法(“找茬拆分法”)

核心逻辑:检查大表,发现违规就“切一刀”,直到没毛病。

📝 实战例题 (来源: Slide 63-66)

  • 原表

  • 依赖 F

  • 候选键:HS (只有 HS 能决定所有人)

步骤演示

  1. 第一刀:检查

    • CS 是候选键(HS)吗?不是。违规!

    • 拆分

      • 表1(病灶): —— 新表,CS是主键,符合BCNF。

      • 表2(剩余):从原表踢掉 G,保留 CS。

  2. 第二刀:检查表2中的

    • 在表2里,候选键还是 HS。C 不是候选键。违规!

    • 拆分

      • 表2-1(病灶): —— 符合BCNF。

      • 表2-2(剩余):从表2踢掉 T,保留 C。

  3. 第三刀:检查表2-2中的

    • 在表2-2里,HR 不是候选键。违规!

    • 拆分

      • 表2-2-1(病灶): —— 符合BCNF。

      • 表2-2-2(剩余):从表2-2踢掉 C,保留 HR。

  4. 收工:检查表2-2-2

    • 剩余依赖 ,且 HS 是候选键。完美!

最终结果


算法二:3NF 分解算法(“规则合成法”)

核心逻辑:先把所有规则列出来,计算 Canonical Cover,按规则造表,最后检查有没有丢了“钥匙”。

📝 实战例题 (来源: Slide 57)

  • 原表

  • 依赖 F

  • 候选键

步骤演示

  1. Step 0:计算 Canonical Cover

    • 此处给定的 F 已经是最小化的(无冗余),所以
  2. Step 1:按规则造表

    • 规则1 表1:

    • 规则2 表2:

    • 规则3 表3:

  3. Step 2:检查候选键(关键!)

    • 问题:现在的表1、2、3里,有没有哪张表包含了原表的老大(候选键 SNO, CNO)?

    • 检查:表3 包含了 SNO 和 CNO。

    • 结论:这就不用补表了。

    • (注:如果表3不存在,我们就必须人为新建一张表4 (SNO, CNO),否则以后没法查全表数据)

  4. Step 3:去重

    • 没有哪张表是另一张表的子集。保留所有。

最终结果


第五部分:考试速记卡 (Cheat Sheet)

概念 口诀/关键词 核心判定
1NF 原子性 一格一值
2NF 别抱半条腿 消除 非主属性 主键的一部分
3NF 别听中间商 消除 非主属性 非主属性
BCNF 老大才能话事 左边必须是 Superkey
正则覆盖 极简主义 等价、右边单属性、无废话
分解原则 无损连接 (公共字段必须是某张表的Key)
3NF 算法 合成+补救 算正则覆盖 造表 查Key (没Key就补Key)
BCNF 算法 找茬+切分 只要左边不是Key 切两半

复习建议

  1. 判定范式:先算候选键,然后看依赖关系是不是指向非主属性(3NF问题)或者左边不是键(BCNF问题)。

  2. 分解题目:如果让你分 3NF,第一步必须是Canonical Cover,最后别忘了检查候选键;如果让你分 BCNF,就盯着非 Key 的决定者切。

如果您喜欢我的文章,可以考虑打赏以支持我继续创作.

其他文章
目录导航 置顶
  1. 1. 第一部分:为什么要瞎折腾?(动机)
  2. 2. 第二部分:拆表的工具——函数依赖 (FD)
    1. 2.1. 1. 三种需要消灭的“坏依赖”
    2. 2.2. 2. 核心计算:闭包 (Closure)
    3. 2.3. 3. 正则覆盖 (Canonical Cover ) —— 难点与计算核心
  3. 3. 第三部分:好设计的标准——范式 (Normal Forms)
  4. 4. 第四部分:怎么拆?—— 分解算法 (Decomposition)
    1. 4.1. 算法一:BCNF 分解算法(“找茬拆分法”)
    2. 4.2. 算法二:3NF 分解算法(“规则合成法”)
  5. 5. 第五部分:考试速记卡 (Cheat Sheet)
请输入关键词进行搜索