数据库设计范式实例讲解
原始数据表(违反1NF)
表名:StudentCourses
学生ID | 学生姓名 | 选课信息(课程ID+课程) | 成绩 | 学院 | 教师 |
---|---|---|---|---|---|
S001 | 张三 | C101-数据库, C102-算法 | 85 | 人工智能学院 | 曾老师 |
S001 | 张三 | C101-数据库, C102-算法 | 90 | 人工智能学院 | 曾老师 |
S002 | 李四 | C101-数据库 | 78 | 人工智能学院 | 曾老师 |
问题:
- 选课信息 字段包含多个课程ID和课程名称的组合值(非原子性),违反 1NF。
- 同一学生的多门课程重复存储冗余信息(如学生姓名、学院、教师)。
第一范式(1NF):拆分非原子字段为多行
要求:每个字段的值不可再分,每列存储原子性数据。
修正后:
将 选课信息 拆分为多行,每行仅含一门课程信息:
学生ID | 学生姓名 | 课程ID | 课程名称 | 成绩 | 学院 | 教师 |
---|---|---|---|---|---|---|
S001 | 张三 | C101 | 数据库 | 85 | 人工智能学院 | 曾老师 |
S001 | 张三 | C102 | 算法 | 90 | 人工智能学院 | 曾老师 |
S002 | 李四 | C101 | 数据库 | 78 | 人工智能学院 | 曾老师 |
第二范式(2NF):消除部分依赖
问题:
- 主键为 (学生ID, 课程ID)。
- 学生姓名 仅依赖 学生ID(部分依赖),课程名称 和 教师 仅依赖 课程ID(部分依赖)。
修正步骤:
- 拆分学生表、课程表、选课表。
学生表 Students
学生ID | 学生姓名 |
---|---|
S001 | 张三 |
S002 | 李四 |
课程表 Courses
课程ID | 课程名称 | 教师 | 学院 |
---|---|---|---|
C101 | 数据库 | 曾老师 | 人工智能学院 |
C102 | 算法 | 曾老师 | 人工智能学院 |
选课表 Enrollments
学生ID | 课程ID | 成绩 |
---|---|---|
S001 | C101 | 85 |
S001 | C102 | 90 |
S002 | C101 | 78 |
第三范式(3NF):消除传递依赖
问题:
- 在 Courses 表中,学院 依赖 教师(假设曾老师属于人工智能学院),而 教师 依赖主键 课程ID,形成传递依赖。
修正步骤:
- 拆分教师与学院的关系。
教师表 Teachers
教师 | 学院 |
---|---|
曾老师 | 人工智能学院 |
课程表 Courses(修正后)
课程ID | 课程名称 | 教师 |
---|---|---|
C101 | 数据库 | 曾老师 |
C102 | 算法 | 曾老师 |
最终设计(符合3NF)
-
Students
学生ID 学生姓名 S001 张三 S002 李四 -
Teachers
教师 学院 曾老师 人工智能学院 -
Courses
课程ID 课程名称 教师 C101 数据库 曾老师 C102 算法 曾老师 -
Enrollments
学生ID 课程ID 成绩 S001 C101 85 S001 C102 90 S002 C101 78
关键区别总结
范式 | 解决的问题 | 修正方法 |
---|---|---|
1NF | 字段值非原子性(组合课程信息) | 拆分为多行,确保每列不可分 |
2NF | 部分依赖(学生姓名、课程名称等仅依赖部分主键) | 拆分实体表和关系表 |
3NF | 传递依赖(学院依赖教师而非直接依赖课程ID) | 拆分教师与学院的关系表 |
原创文章,作者:曾确令,如若转载,请注明出处:https://www.zengqueling.com/sjksjfssljj/