在前五章中,我们学习了数据库的基础、操作语言SQL以及安全与完整性保障。然而,一个数据库系统是否优秀,其根基在于其逻辑结构的设计。如果模式设计不当,即使有再强大的SQL和再严密的安全措施,也难以避免数据冗余、插入/删除/更新异常等顽疾。第六章“关系数据理论”正是为我们提供了一套科学、严谨的理论工具,用以评估和改进关系模式的质量。
本章的核心思想是规范化(Normalization),它通过分析数据依赖关系,指导我们将一个“坏”的关系模式分解为多个“好”的关系模式。
一、 问题的提出:一个糟糕的模式能有多糟?
让我们从一个具体的例子开始:假设我们要设计一个描述学生选课信息的单一表Student(Sno, Sdept, Mname, Cname, Grade)。
- 语义:一个学生属于一个系,一个系只有一名主任;学生可以选多门课,每门课有成绩。
- 函数依赖:
Sno → Sdept,Sdept → Mname,(Sno, Cname) → Grade。
这个看似简单的模式,却隐藏着巨大的问题:
- 数据冗余:系主任的名字会随着该系每个学生的每门课程而重复存储。
- 更新异常:如果某系更换了主任,需要修改该系所有学生的记录,极易出错。
- 插入异常:一个新成立的系,如果没有学生,就无法将系及其主任的信息存入数据库。
- 删除异常:如果一个系的所有学生都毕业了,删除学生记录的同时,也会意外丢失该系的信息。
根本原因:模式中存在不合适的数据依赖(Data Dependency)。解决之道就是模式分解(Decomposition),而规范化理论则为我们指明了分解的方向和标准。
二、 核心武器:函数依赖与范式
规范化理论建立在函数依赖(Functional Dependency, FD)这一核心概念之上。
- 函数依赖 (X → Y):如果在一个关系中,属性集X的值唯一决定了属性集Y的值,那么称Y函数依赖于X。例如,学号(Sno)唯一决定了学生所在系(Sdept),即
Sno → Sdept。 - 码(Key):能够唯一标识一个元组的最小属性集。主码是被选定的候选码。
基于函数依赖和码的概念,我们定义了一系列范式(Normal Form),它们代表了关系模式满足不同级别规范要求的状态。
范式的演进之路
第一范式(1NF):这是关系模式的基本要求,即表中的每个分量都是不可再分的数据项。我们的所有关系都必须首先满足1NF。
第二范式(2NF):在1NF的基础上,消除非主属性对码的部分函数依赖。
- 部分函数依赖:如果一个非主属性依赖于码的一部分,而非整个码。
- 例子:在
SLC(Sno, Sdept, Sloc, Cno, Grade)中,码是(Sno, Cno)。但Sdept和Sloc只依赖于Sno(码的一部分),这就是部分依赖。 - 解决:分解为
SC(Sno, Cno, Grade)和SL(Sno, Sdept, Sloc)。
第三范式(3NF):在2NF的基础上,消除非主属性对码的传递函数依赖。
- 传递函数依赖:如果
X → Y且Y → Z(Y不决定X),那么X → Z是传递依赖。 - 例子:在
SL(Sno, Sdept, Sloc)中,Sno → Sdept且Sdept → Sloc,所以Sno → Sloc是传递依赖。 - 解决:分解为
SD(Sno, Sdept)和DL(Sdept, Sloc)。
- 传递函数依赖:如果
BC范式(BCNF):比3NF更严格。它要求对于每一个非平凡的函数依赖
X → Y,决定因素X都必须包含一个候选码。- 意义:不仅消除了非主属性的问题,也消除了主属性对码的部分和传递依赖。
- 例子:在
STJ(S, T, J)(学生-教师-课程)中,(S,J)→T,(S,T)→J,T→J。虽然它是3NF(所有属性都是主属性),但T→J的决定因素T不是候选码,因此不满足BCNF。 - 解决:分解为
ST(S, T)和TJ(T, J)。
第四范式(4NF):处理多值依赖(Multivalued Dependency, MVD)的问题。当一个关系中存在一对多的联系,且这些联系彼此独立时,就会产生多值依赖,导致数据冗余。
- 例子:
Teaching(C, T, B)(课程-教师-参考书),一门课程对应多名教师和多本参考书,且教师和参考书之间没有直接联系。这会产生大量的组合冗余。 - 解决:分解为
CT(C, T)和CB(C, B)。
- 例子:
规范化的基本思想:低一级范式的关系模式,通过投影分解,可以转换为若干个高一级范式的关系模式集合。但要注意,并非规范化程度越高越好,需要结合具体应用需求权衡。
三、 理论基石:Armstrong公理系统
如何从已知的函数依赖集F推导出所有隐含的函数依赖?Armstrong公理系统提供了完备且有效的推理规则:
- 自反律:若
Y ⊆ X,则X → Y。 - 增广律:若
X → Y,则XZ → YZ。 - 传递律:若
X → Y且Y → Z,则X → Z。
基于这三条公理,可以推导出合并律、分解律、伪传递律等。更重要的是,我们可以利用它来计算属性集的闭包(X⁺),这对于求解候选码和判断函数依赖是否成立至关重要。
四、 模式分解的艺术:无损连接 vs. 保持依赖
将一个关系模式分解后,我们必须确保分解是“有意义”的,主要看两个标准:
- 无损连接性(Lossless Join):分解后的各个关系通过自然连接操作,能够完全恢复原始关系,不丢失任何信息。
- 保持函数依赖(Preserve Dependency):原关系中的所有函数依赖,在分解后的关系中都能得到体现或推导出来,从而保证数据的完整性约束依然有效。
关键点:这两个标准是相互独立的。一个好的分解方案应该同时满足无损连接和保持函数依赖。例如,将SL(Sno, Sdept, Sloc)分解为ND(Sno, Sdept)和DL(Sdept, Sloc)就是一个既无损又保持依赖(Sdept → Sloc)的完美方案。
结语:理论与实践的桥梁
第六章的关系数据理论,为我们从“凭经验设计”走向“科学化设计”提供了强大的理论支撑。它告诉我们,优秀的数据库模式不是偶然形成的,而是可以通过分析数据依赖、遵循范式原则、运用分解技巧来精心构造的。
掌握了这套理论,我们就拥有了评估和优化数据库设计的能力。在后续的学习和实践中,无论是进行概念设计还是逻辑设计,这些原理都将成为我们最可靠的指南针。