概述
在数据库设计中,范式(Normal Forms, NF)是用来规范化数据库表结构,以减少冗余数据和提高数据一致性与完整性的重要工具。
函数依赖
完全函数依赖与部分函数依赖
完全函数依赖
定义:
完全函数依赖表示的是在一个关系中,若某个非主属性数据项依赖于全部关键字,则称这种依赖为完全函数依赖。换句话说,如果非主属性B函数依赖于构成某个候选关键字的一组主属性A,而且A的任何一个真子集不能被B函数依赖,则称B完全函数依赖于A。
举例:
以成绩表为例,该表包含 (学号,课程号,成绩) (学号,课程号,成绩) (学号,课程号,成绩)三个属性。其中, (学号,课程号) (学号,课程号) (学号,课程号)是一个候选键,因为它们共同确定了一个唯一的成绩。
- 完全函数依赖:在这个例子中, (学号,课程号) → 成绩 (学号,课程号)→ 成绩 (学号,课程号)→成绩是一个完全函数依赖。因为成绩完全依赖于学号和课程号的组合,单独的学号或课程号都不能确定成绩。
部分函数依赖
定义:
部分函数依赖是指在一个关系中,如果 X → Y X→Y X→Y,并且存在 X X X的一个真子集 X 0 X₀ X0,使得 X 0 → Y X₀→Y X0→Y,则称 Y Y Y对 X X X部分函数依赖。这意味着 Y Y Y不仅依赖于 X X X的全部,还依赖于 X X X的某个真子集。
举例:
以成绩表为例,假设该模式包含 (学号,课程号,成绩,年龄) (学号,课程号,成绩,年龄) (学号,课程号,成绩,年龄)四个属性。
- 部分函数依赖:在这个例子中,如果 学号 学号 学号能单独确定 年龄 年龄 年龄,而 (学号,课程号) (学号,课程号) (学号,课程号)共同确定 成绩 成绩 成绩。那么, (学号,课程号) → 年龄 (学号,课程号)→ 年龄 (学号,课程号)→年龄就是一个部分函数依赖,因为 年龄 年龄 年龄不仅依赖于 (学号,课程号) (学号,课程号) (学号,课程号)的组合,还依赖于 学号 学号 学号这个真子集。
归纳:
- 完全函数依赖强调的是非主属性对全部关键字的依赖,即不存在关键字的真子集能够确定非主属性。
- 部分函数依赖则允许非主属性对关键字的某个真子集也存在依赖关系。
范式
第一范式(1NF - First Normal Form)
定义:
1NF要求数据库表中的每个列(或称为属性、字段)都包含不可再分的原子数据,也就是说每个单元格中只包含一个值。不应该有多值属性或重复组。
要点:
- 每个表中的每一列都必须包含不可再分的原子数据。
- 表中的每一行必须具有唯一的标识符,通常是主键。
举例:
假设我们有一个表示图书信息的表,初始设计如下:
图书信息 | 图书号 | 书名 | 作者 | 出版社 |
---|---|---|---|---|
… | … | … | … | … |
示例 | 123 | 《编程基础》;《数据库原理》 | 李四,王五 | 清华大学出版社;机械工业出版社 |
这个表不满足1NF,因为“书名”和“作者”列包含了多个值(由分号分隔),它们是可以再分的。为了满足1NF,我们需要将这些列拆分为多个列,如下:
图书号 | 书名1 | 作者1 | 出版社1 | 书名2 | 作者2 | 出版社2 |
---|---|---|---|---|---|---|
123 | 《编程基础》 | 李四 | 清华大学出版社 | 《数据库原理》 | 王五 | 机械工业出版社 |
但上述设计仍然不是最佳实践,因为它引入了不必要的冗余。更常见的方法是将每本书的信息分别存储在不同的行中,如下所示:
图书号 | 书名 | 作者 | 出版社 |
---|---|---|---|
123 | 《编程基础》 | 李四 | 清华大学出版社 |
456 | 《数据库原理》 | 王五 | 机械工业出版社 |
第二范式(2NF - Second Normal Form)
定义:
2NF建立在1NF的基础上,要求关系模式中的所有非主属性都完全依赖于候选键(或称为主键),而不是仅依赖于候选键的一部分。
要点:
- 满足1NF。
- 非主属性必须完全依赖于候选键。
举例:
假设我们有一个表示学生选课信息的表,初始设计如下:
学号 | 课程号 | 成绩 | 课程学分 |
---|---|---|---|
… | … | … | … |
N01 | C01 | 90 | 3 |
N01 | C02 | 85 | 4 |
N02 | C01 | 88 | 3 |
在这个例子中, 学号( S N O ) 学号(SNO) 学号(SNO)和 课程号( C N O ) 课程号(CNO) 课程号(CNO)的组合是主键(候选键)。然而, “课程学分” “课程学分” “课程学分”这一非主属性仅依赖于课程号 ( C N O ) (CNO) (CNO),而不是完全依赖于主键 ( S N O , C N O ) (SNO, CNO) (SNO,CNO)。这违反了2NF。
为了满足2NF,我们需要将“课程学分”这一属性移到一个新的表中,该表以课程号(CNO)为主键,如下所示:
表1:选课信息
学号 | 课程号 | 成绩 |
---|---|---|
N01 | C01 | 90 |
N01 | C02 | 85 |
N02 | C01 | 88 |
表2:课程信息
课程号 | 课程学分 |
---|---|
C01 | 3 |
C02 | 4 |
这样,我们就通过分解原始表来满足了2NF,减少了数据冗余并提高了数据一致性。
第三范式(3NF - Third Normal Form)
定义:
3NF建立在2NF的基础上,要求关系模式中的所有非主属性都不传递依赖于候选键。
换句话说,如果非主属性 A A A依赖于另一个非主属性 B B B,而 B B B又依赖于候选键 C C C,那么 A A A不能直接依赖于 B B B,而必须直接依赖于 C C C。
B → A , C → B (非3NF) B → A , C → B \tag{非3NF} B→A,C→B(非3NF)
C → A , C → B (3NF) C → A , C → B \tag{3NF} C→A,C→B(3NF)
要点:
- 满足2NF。
- 消除传递依赖。
举例:
考虑一个表示学生信息的表,其中包含了学生、课程、成绩以及课程对应的教师信息。
原始设计可能如下:
学生ID | 学生姓名 | 课程号 | 课程名 | 成绩 | 教师ID | 教师姓名 |
---|---|---|---|---|---|---|
… | … | … | … | … | … | … |
在这个例子中,学生ID和课程号的组合是主键(候选键)。
然而,“教师姓名”这一非主属性仅依赖于“教师ID”,而“教师ID”又依赖于“课程号”。
这构成了一个传递依赖,因为“教师姓名”间接地依赖于主键的一部分(即“课程号”),而不是直接依赖于整个主键(学生ID和课程号)。
为了满足3NF,我们需要将“教师”相关的信息移到一个新的表中,如下所示:
表1:学生选课信息
学生ID | 学生姓名 | 课程号 | 成绩 |
---|---|---|---|
… | … | … | … |
表2:课程信息
课程号 | 课程名 | 教师ID |
---|---|---|
… | … | … |
表3:教师信息
教师ID | 教师姓名 |
---|---|
… | … |
Boyce-Codd范式(BCNF - Boyce-Codd Normal Form)
定义:
BCNF是由Boyce和Codd提出的,它比3NF更为严格。BCNF要求关系模式中的所有属性(包括主属性)都不传递依赖于候选键。
要点:
- 所有非主属性对每一个候选键都是完全函数依赖。
- 所有的主属性对每一个不包含它的候选键,也是完全函数依赖。
- 没有任何属性完全函数依赖于非候选键的任何一组属性。
解释:
BCNF不仅要求非主属性不传递依赖于候选键,还要求主属性也不传递依赖于候选键。这意味着在BCNF中,任何属性都不能间接地依赖于候选键的任何一部分。这进一步减少了数据冗余和更新异常的可能性。
由于BCNF的定义较为复杂,通常在实际应用中,数据库设计者会首先尝试满足1NF、2NF和3NF,然后在必要时才考虑BCNF。这是因为满足BCNF的数据库模式可能更加复杂,不易于理解和维护。然而,在某些情况下,特别是在需要高度数据一致性和完整性的应用中,BCNF可能是一个有用的工具。