lecture4 ICFD

94 阅读4分钟

数据库函数依赖、闭包、超键与候选键完全指南

一、函数依赖(Functional Dependency)

定义

  • 符号X → Y
  • 含义:X函数决定Y,或者说Y函数依赖于X
  • 形式化定义:对于关系R的任意两个元组t1和t2,如果t1[X] = t2[X],则t1[Y] = t2[Y]

关键理解

  • 箭头方向:从决定因素指向依赖因素
  • 正确理解:X → Y 表示"X决定Y"或"Y依赖于X"
  • 错误理解:X → Y 不是"X依赖于Y"

示例

{学号} → {姓名} 表示:

  • 学号决定姓名
  • 姓名依赖于学号
  • 相同学号对应相同姓名

二、属性集闭包(Closure of Attributes)

定义

给定属性集S和函数依赖集F,S⁺表示通过F中的函数依赖能够推导出的所有属性的集合。

闭包算法

输入:属性集S,函数依赖集F 输出:S⁺

步骤

  1. 初始化 result = S
  2. 重复直到result不再变化:
    • 对每个FD X → Y ∈ F:
      • 如果 X ⊆ result:
        • result = result ∪ Y
  3. 返回result

示例计算

已知:R(X,Y,U,V,W),F = {X→Y, U,V→W, V→X}

计算过程:

  • {X}⁺:

    • 初始:{X}
    • X→Y:加入Y → {X,Y}
    • 停止
    • {X}⁺ = {X,Y}
  • {V}⁺:

    • 初始:{V}
    • V→X:加入X → {V,X}
    • X→Y:加入Y → {V,X,Y}
    • 停止
    • {V}⁺ = {V,X,Y}

三、超键(Superkey)与候选键(Candidate Key)

超键定义

能唯一标识关系中每个元组的属性集。

判断条件:S⁺ = 所有属性

候选键定义

最小的超键(不含多余属性的超键)。

判断条件

  1. S⁺ = 所有属性(超键条件)
  2. S的任何真子集都不是超键(最小性条件)

关系说明

  • 所有候选键都是超键
  • 不是所有超键都是候选键
  • 一个关系可能有多个候选键
  • 主键是选定的一个候选键

四、系统化寻找候选键的方法

步骤1:属性分类

基于函数依赖集F:

  • L:只出现在FD左边的属性
  • R:只出现在FD右边的属性
  • LR:在左右都出现的属性
  • N:不出现在任何FD中的属性

步骤2:从(L ∪ N)开始

  • 计算(L ∪ N)⁺
  • 如果(L ∪ N)⁺ = 所有属性,则(L ∪ N)是候选键
  • 否则,逐步添加LR中的属性

步骤3:验证最小性

对于每个找到的超键S:

  • 检查S的每个真子集S'
  • 如果存在S'⁺ = 所有属性,则S不是候选键

五、详细例题解析

例题1:基础闭包计算

已知:R(A,B,C,D,E),F = {A→BC, CD→E, B→D, E→A} :{A}⁺、{B}⁺

  • {A}⁺:

    • {A} → A→BC → {A,B,C}
    • {A,B,C} → B→D → {A,B,C,D}
    • {A,B,C,D} → CD→E → {A,B,C,D,E}
    • {A}⁺ = {A,B,C,D,E}
  • {B}⁺:

    • {B} → B→D → {B,D}
    • 无法再加入其他属性
    • {B}⁺ = {B,D}

例题2:单候选键情况

已知:R(A,B,C,D),F = {A→B, B→C, C→D, D→B} :所有候选键

  1. 计算单属性闭包:

    • {A}⁺ = {A,B,C,D} ⇒ 超键
    • {B}⁺ = {B,C,D} ≠ 所有属性
    • {C}⁺ = {B,C,D} ≠ 所有属性
    • {D}⁺ = {B,C,D} ≠ 所有属性
  2. 验证最小性:

    • A是单属性,没有真子集
    • {A}是候选键
  3. 结论:唯一候选键是{A}

例题3:多候选键情况

已知:R(A,B,C,D),F = {AB→C, C→D, D→A} :所有候选键

  1. 属性分类:

    • L: {B}(只出现在左边AB→C中)
    • R: ∅
    • LR: {A,C,D}(都出现在左右)
    • N: ∅
  2. 从{B}开始:

    • {B}⁺ = {B} ⇒ 不是超键
  3. 测试组合:

    • {A,B}⁺:

      • {A,B} → AB→C → {A,B,C}
      • {A,B,C} → C→D → {A,B,C,D}
      • {A,B}⁺ = 所有属性 ⇒ 候选键
    • {B,C}⁺:

      • {B,C} → C→D → {B,C,D}
      • {B,C,D} → D→A → {A,B,C,D}
      • 但{C}⁺ = {C,D,A} = 所有属性 ⇒ {B,C}不是候选键
    • {B,D}⁺:

      • {B,D} → D→A → {A,B,D}
      • {A,B,D} → AB→C → {A,B,C,D}
      • 检查最小性:{B}⁺、{D}⁺都不是超键 ⇒ 候选键
    • {C}⁺:

      • {C} → C→D → {C,D}
      • {C,D} → D→A → {A,C,D}
      • {C}⁺ = {A,C,D} ≠ 所有属性?错误! 实际上:{C} → C→D → {C,D} → D→A → {A,C,D} 但{A,C,D}中无法得到B,所以{C}⁺ = {A,C,D} ≠ 所有属性

    修正:

    • {C}⁺ = {A,C,D} ≠ 所有属性 ⇒ 不是候选键
  4. 最终候选键:{A,B}、{B,D}

例题4:判断FD是否蕴含

已知:F = {A→B, BC→D} :A→D是否被F逻辑蕴含?

  • 计算{A}⁺:
    • {A} → A→B → {A,B}
    • 停止(BC→D的左边BC不包含于{A,B})
  • {A}⁺ = {A,B}
  • D ∉ {A}⁺ ⇒ A→D不被F蕴含

六、SQL验证候选键

检查属性集S是否为超键

-- 如果返回空结果,则S唯一(可能是超键)
SELECT S
FROM R
GROUP BY S
HAVING COUNT(*) > 1;