(数据库原理与应用)关系数据库设计 -8(持续更新中)

567 阅读11分钟

1. 函数依赖

简介

在关系数据库中,函数依赖(Functional Dependency)是一种重要的概念,用于描述一个属性或属性集合对于另一个属性或属性集合的依赖关系。函数依赖定义了一个属性的值如何依赖于另一个属性的值。函数依赖通常用箭头符号 "->" 表示。

具体来说,如果在一个关系中,对于给定的属性或属性组合,属性A的值唯一地决定了属性B的值,那么我们可以表示为 A -> B。这意味着在给定关系中,对于相同的A值,B值总是相同的。

例如,考虑一个包含"学生ID"、"学生姓名"和"学生年龄"的关系表。如果我们有一个函数依赖 "学生ID -> 学生姓名",那么这意味着在同一个学生ID下,学生姓名的值是唯一的,即一个学生ID对应一个学生姓名。这是一种单一属性的函数依赖。

函数依赖与超码和候选码之间的关系

  • 如果一个属性集合α函数依赖于另一个属性集合β,那么β必定是一个超码(可能是候选码),因为它能够唯一确定α的值。
  • 例如,如果学生ID → 学生姓名,则学生ID是一个候选码或超码,而学生姓名是一个函数依赖于学生ID的属性。

平凡的函数依赖

平凡的函数依赖是一种特殊的函数依赖,其特点是决定属性集合(α)包含了依赖属性集合(β)。换句话说,在平凡的函数依赖中,依赖属性集合β是决定属性集合α的子集。

具体来说,如果一个函数依赖α → β是平凡的,那么α和β必定相同。 这意味着依赖属性集合β中的属性在决定属性集合α中,或者可以说决定属性集合α包含了依赖属性集合β。这样的函数依赖通常不会提供有用的信息,因为它没有描述属性之间的真正依赖关系,只是确认了某些属性自身的存在。

例如,考虑以下关系模式(表)R:

R = {学生ID, 学生姓名, 学生ID}

在这种情况下,如果存在函数依赖学生ID → 学生ID,这被认为是一个平凡的函数依赖,因为它仅确认学生ID属性自身的存在,没有提供任何额外的信息。

平凡的函数依赖通常被视为没有实际用途,因为它们没有帮助我们理解数据表中的属性之间的有意义的依赖关系。在数据库设计和规范化过程中,通常会考虑并强调非平凡的函数依赖,这些依赖关系提供了有关数据的更有用和有意义的信息。

函数依赖集

函数依赖集是所有属性之间的函数依赖关系的集合。函数依赖集用于描述在一个关系模式(表)中,一个属性集合如何依赖于另一个属性集合。

例如,考虑以下关系模式R,包括属性A、B、C、D:

R = {A, B, C, D}

一个可能的函数依赖集可以是:

  1. A → B:属性A的值决定属性B的值。
  2. C, D → A:属性C和D的值共同决定属性A的值。
  3. B → C, D:属性B的值决定属性C和D的值。
  • 如果一个关系 r 没有违反函数依赖集 F, 那么称关系 r 满足函数依赖集 F ( r satisfies F )

  • 如果关系模式 R 的所有关系都满足函数依赖集 F, 那么称函数依赖集F 在关系模式 R 上成立 ( F holds on R )

函数依赖集的等价性

设 F1 和 F2 是两个函数依赖集,如果由F1 可以推出 F2 的所有函数依赖,由F2 也可以推出 F1 的所有函数依赖,就说 F1 和 F2 是等价的

例如:

{A → B, B → C}

{A → B, B → C, A→C} 是等价的

2.属性集的闭包

简介

属性集的闭包用于描述一个属性集合经过一系列函数依赖操作后所能推导出的属性集合。属性集的闭包通常用符号来表示,通常写作 {X}^+,其中X是初始属性集合。

闭包操作通过不断应用函数依赖规则来确定一个属性集合中可以推导出的所有属性。以下是函数依赖规则的一些示例:

  1. 反身性规则:如果A包含在X中,那么A也包含在{X}^+中。
  2. 广泛性规则:如果X → Y,那么{X}^+中也包含Y。
  3. 传递规则:如果X → Y,Y → Z,那么{X}^+中包含Z。

通过这些规则,可以计算出属性集合的闭包,以了解它们之间的依赖关系。闭包是一个属性集合,其中包含了X及其可以推导出的所有属性。这对于数据库设计和规范化非常重要,因为它帮助设计师确定一个属性集合是否包含其他属性的决定属性,从而可以更好地组织数据库表。

例如,假设有一个关系模式R = {A, B, C, D},并且有以下函数依赖:

  1. A → B
  2. B → C

如果我们计算{A}^+,我们可以得到{A, B, C},因为A决定了B,B又决定了C。这表示A的闭包包括A、B和C。这对于确定属性的超码和候选码以及数据库规范化都非常有用。

计算属性集的闭包的算法

result := α;

不断使用 F 中的函数依赖,把 result 能决定的其他属性都加进 result,直到不能再添加属性到 result 为止,输出 result 作为α^+

R = (A, B, C, G, H, I)

F = { A → B

A → C

CG → H

CG → I

B → H }

计算 (AG)^+

result = AG

A → B -----------result = ABG

A → C ----------- result = ABCG

CG → H ----------- result = ABCGH

CG → I ----------- result = ABCGHI

B → H ----------- result = ABCGHI

result 已经包含了全部属性, 可以停止

计算步骤解释

  1. 初始闭包:将{AG}加入到闭包中,即{AG}^+ = {AG}。

  2. 使用广泛性规则(规则2):检查F中的函数依赖,看是否有其他属性可以添加到闭包中。

    • 根据F中的函数依赖 A → B,我们可以将B添加到闭包中,因为A → B → H(根据 F 中的 B → H)。
    • 根据F中的函数依赖 A → C,我们可以将C添加到闭包中。

现在,{AG}^+ = {AG, B, C}。

  1. 再次使用广泛性规则:继续检查F中的函数依赖,看是否有其他属性可以添加到闭包中。

    • 根据F中的函数依赖 CG → H,由于C已经在闭包中,我们可以将H添加到闭包中。
    • 根据F中的函数依赖 CG → I,由于C已经在闭包中,我们可以将I添加到闭包中。

现在,{AG}的闭包为{AG, B, C, H, I}。

  1. 再次使用广泛性规则:检查其他函数依赖,但在这种情况下,没有其他函数依赖可以应用,因为所有的函数依赖都已经包含在闭包中。

最终,{AG}的闭包是{AG, B, C, H, I}。这表示属性集合{AG}经过给定函数依赖集F的作用后,能推导出的所有属性。这对于数据库规范化和属性依赖分析非常有用。

属性闭包的作用

  • 判断一个属性集是否超码

要判断 α 是不是 R 的超码,只要看 α^+ 是不是包含 R

  • 判断一个函数依赖是否成立

要判断 α → β 是不是成立,只要看β是否包含与α^+

  • 简便地计算函数依赖集的闭包

下一节将提及

3.规范覆盖(Canonical Cover)

函数依赖集中的某些函数依赖是多余的

如:

{A → B, B → C, A → C}

可以简化为等价的函数依赖集合

{A → B, B → C}

函数依赖中的某些属性是多余的

如:

{A → B, B → C, A → CD}

可以简化为等价的函数依赖集合

{A → B, B → C, A → D}

{A → B, B → C, AC → D}

可以简化为等价的函数依赖集合

{A → B, B → C, A → D}

把函数依赖集 F 中多余的函数依赖和多余的属性删除,得到“最小的”函数依赖集合,称为 F 的最小覆盖或规范覆盖

规范覆盖的定义

函数依赖集 F 的最小覆盖 Fc 满足以下条件:

  • F 和 Fc是等价的
  • Fc 的所有函数依赖都没有多余属性
  • Fc 的每个函数依赖的决定部分都是唯一的

规范覆盖的算法

Fc = F

不断重复以下步骤

合并 Fc 中有相同决定部分的函数依赖:把 α1 → β1 和 α1 → β2 合并为 α1 → β1β2

把 Fc 中的多余属性删掉

直到 Fc 不再发生变化

例:

R = (A, B, C )

F = { A → BC

B → C

A → B

AB → C }

Fc = F

把 A → BC 和 A → B 合并为 A → BC

Fc = { A → BC, B → C, AB → C }

AB → C 中的 A 是多余的

删掉 A 后, Fc = {A → BC, B → C}

A → BC 中的 C 是多余的

删掉 C 后, Fc = {A → B, B → C }

已经不能再合并,也没有多余属性,算法结束

不唯一性

一个函数依赖集的最小覆盖不是唯一的,以下四个函数依赖集都是

F = {A → BC, B → AC, C → AB } 的最小覆盖

{ A→B, B→C, C→A }

{ A→B, B→AC, C→B }

{ A→C, C→B, B→A}

{ A→C, B→C, C→AB}

4.模式分解(Decomposition)

可以把一个关系模式分解成若干个关系模式

例如:把 instr_dept (ID, name, salary, dept_name, building,budget ) 分解成

department (dept_name, building, budget) 和 instructor (ID, name, salary, dept_name)

无损分解(Lossless Decomposition)

将一个关系模式(关系表)分解成两个或多个较小的关系模式,而不丢失原始关系的任何信息。这意味着通过合适的分解,我们可以重新组合分解后的关系,得到与原始关系完全相同的信息。

例:

R = (A, B, C)

F = {A → B, B → C}

如果把R分解成:R1 = (A, B), R2 = (B, C)

这种分解是无损的 R1 ∩ R2 = {B} , B → BC

如果把R分解成:R1 = (A, B), R2 = (A, C)

这种分解也是无损的 R1 ∩ R2 = {A}, A → AB

即满足分解过后R1和R2的交集能推出R1或者R2

5.函数依赖集的闭包(Closure of a Set of Functional Dependencies)

由一些函数依赖,可以推断(logically implied)其他的一些函数依赖,例如:

由 A → B 和 B → C, 可推断 A → C

由函数依赖集 F 可推断出的所有函数依赖所组成的集合,叫做 F 的闭包,记为 F^+

F^+ 是 F 的超集

例:

设关系模式 R = (A, B, C),函数依赖集{A → B, B → C, A → C}是否函

数依赖集{A → B, B → C}的闭包?

不是,函数依赖集{A → B, B → C}的闭包是:

{ A→B, A→C, A→AB, A→AC, A→BC, A→ABC

B → C, B → BC

AB → C, AB → AC, AB → BC, AB → ABC

AC → B, AC → AB, AC → BC, AC → ABC

A → A

B → B

C → C

AB → A

AB → B

AB → AB

AC → A

AC → C

AC → AC

BC → B

BC → C

BC → BC

ABC → A

ABC → B

ABC → C

ABC → AB ABC → BC

ABC → AC

ABC → ABC }

设 F1 和 F2 是两个函数依赖集,F1 和 F2 有相同的闭包可以推出F1 和 F2 是等价的,反之亦然

6.Armstrong 公理

Armstrong公理是关系数据库中函数依赖理论的基础,用于描述数据库表中属性之间的依赖关系。这些公理是由数学家和计算机科学家 William W. Armstrong 提出的。函数依赖描述了一个关系模式中的属性之间的关系,其中一个属性的值的变化可以唯一确定另一个属性的值。

Armstrong提出了一组公理,用于推导和验证关系数据库中的函数依赖。这些公理包括:

  1. 自反性(Reflexivity): 如果 X 是属性集合,那么 X → X 是成立的。
  2. 增强(Augmentation): 如果 X → Y 是成立的,那么对于任何属性集合 Z,XZ → YZ 也是成立的。
  3. 传递性(Transitivity): 如果 X → Y 和 Y → Z 都成立,那么 X → Z 也是成立的。