题目
数据库三范式
答案
@[toc] --- 数据库三范式是关系数据库的设计原则,它帮助我们规划出结构合理、稳定性好的关系型数据库 ## 第一范式(1NF):确保每列都是不可拆分的 这意味着每一列的值都不能再分解成更小的值。 比如一张学生表 Students,包含字段(学号,姓名,性别,出生年月日) | Id(学号) | Name(姓名) | Sex(性别) | Birth(出生日期) | | ---------- | ------------ | ----------- | ----------------- | | 1 | 小牛肉 | 男 | 2023-05-01 | 如果出生日期在业务中还需要再分成(出生年,出生月,出生日),那么这个设计就不符合第一范式。 ## 第二范式(2NF):在第一范式的基础上,确保非主键列完全依赖于主键,而不是依赖于主键的一部分 这意味着非主键列必须依赖于完整的主键,而不是依赖于主键的一部分。 比如一张选课表 StudentCourse,包含字段(学号、课程号、姓名、学分),**学号和课程号是主键**,唯一确定一行记录: | 学号 | 课程号 | 姓名 | 学分 | | ---- | ------ | ------ | ---- | | 1 | 18 | 小牛肉 | 4.0 | 这个表显然说明了两段信息: - 学生信息(学号,姓名) - 课程信息(课程号,学分) 学分依赖于学号和课程号,完全依赖于主键;但是很显然学生姓名只需要依赖于学号,不依赖于课程号,即部分依赖于主键,所以不满足第二范式。 如果不满足第二范式,那么**可能会存在下述问题**: - `数据冗余`:每条记录都含有相同信息。比如学号 = 1 的学生选了课程号 18 和 20 的课程,那么这张表中学号 1 和姓名 “小牛肉” 就会出现 2 次: | 学号 | 课程号 | 姓名 | 学分 | | ---- | ------ | ------ | ---- | | 1 | 18 | 小牛肉 | 4.0 | | 1 | 20 | 小牛肉 | 2.0 | - `删除异常`:删除所有学生成绩,就会把课程信息(课程号,学分)全删除了 - `插入异常`:如果学生未选课,则无法将学生信息存入数据库 - `更新异常`:如果需要调整某门课程的学分,那么所有涉及到这门课程的记录都需要进行调整 上述示例满足第二范式的设计应该是: - 学生表:`Student` (学号, 姓名),主键是学号 - 课程表:`Course` (课程号, 学分),主键是课程号 - 成绩表:`StudentCourse`(学号, 课程号, 成绩),主键是学号和课程号 ## 第三范式(3NF):在第二范式的基础上,确保非主键列不存在传递依赖 如果一个关系满足第二范式,并且**在两个 (或多个) 非主键属性之间不存在函数依赖** (非主键属性之间的函数依赖也称为传递依赖),那么这个关系就满足第三范式。 > 举个例子,一张表中有 A B C 三个字段,B 依赖于 A(A→B),C 依赖于 B(B→C),那么则称 C 传递依赖于 A(A→C) 简单来说,**3NF 要求任何字段不能由其他字段派生出来,它要求字段没有冗余,即不存在传递依赖**。 比如一张学生信息表,包含字段(学号、姓名、年龄、学院编号、学院名称、学院电话),**学号是主键**,唯一确定一行记录: | 学号 | 姓名 | 年龄 | 学院编号 | 学院名称 | 学院电话 | | ---- | ------ | ---- | -------- | ---------- | -------- | | 1 | 小牛肉 | 18 | 111 | 计算机学院 | 12345 | 这个表显然说明了两段信息: - 学生信息(学号、姓名、年龄) - 学院信息(学院编号、学院名称、学院电话) 每一行记录中的学院编号都依赖于学号(学号→学院编号),而学院名称依赖于学院编号(学院编号→学院名称),即学院名称传递依赖于学号(学号→学院名称) 如果不满足第三范式,**可能会存在下述问题**: - `数据冗余` - `更新异常` 上述示例满足第二范式的设计应该是: - 学生信息(学号、姓名、年龄、学院编号):主键是学号 - 学院信息(学院编号、学院名称、学院电话):主键是学院编号