数据库设计范式实例讲解
原始数据表(违反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/