数据库三范式详解
数据库三范式详解
什么是数据库范式
设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
一范式
数据库表中的所有字段值都是不可分解的原子值。[字段原子性,不可分]
例:学生表
学生编号 | 学生姓名 | 联系方式 |
---|---|---|
1 | 张三 | 1@qq.com |
2 | 李四 | 12354534463 |
3 | 王五 | 12351255612 |
在这个学生表中联系方式可分为多种,不满足一范式中的所有字段值是不可分解的原子值。
下面对此表进行修改使其满足一范式:
学生编号 | 学生姓名 | 邮箱 | 电话 |
---|---|---|---|
1 | 张三 | 1@qq.com | 12353466737 |
2 | 李四 | 2@qq.com | 12354534463 |
3 | 王五 | 3@qq.com | 12351255612 |
二范式
建立在一范式的基础之上,要求所有非主键字段完全依赖主键,不要产生部份依赖。[有主键,非主键字段完全依赖主键]
例:学生表
这张表描述了学生和老师的关系(多对多)
学生编号 | 学生姓名 | 老师编号 | 老师姓名 |
---|---|---|---|
1 | 张三 | 01 | 张老师 |
2 | 李四 | 02 | 王老师 |
3 | 王五 | 01 | 张老师 |
此时没有主键,不满足二范式,做出如下修改
(学生编号 | 老师编号)(pk) | 学生姓名 | 老师姓名 |
---|---|---|---|
1 | 01 | 张三 | 张老师 |
2 | 02 | 李四 | 王老师 |
3 | 01 | 王五 | 张老师 |
此时我们将学生编号与老师编号设为复合主键,此时学生姓名依赖学生编号,老师姓名依赖老师编号,不满足二范式中非主键字段完全依赖主键。会造成数据的冗余。此时为了让此表满足二范式,可以使用三张表来表示此表的多对多关系。
即:学生表;教师表;学生教师关系表 如下
学生表
学生编号 | 学生姓名 |
---|---|
1 | 张三 |
2 | 李四 |
3 | 王五 |
教师表
老师编号 | 老师姓名 |
---|---|
01 | 张老师 |
02 | 王老师 |
关系表
id(pk) | 学生编号(fk) | 老师编号(fk) |
---|---|---|
1 | 1 | 01 |
2 | 2 | 02 |
2 | 3 | 01 |
此时表满足二范式。
多对多怎么设计:三张表,关系表两个外键!
三范式
建立在第二范式基础之上,要求所有非主键字段直接依赖主键,不要产生传递依赖。
例:学生表
学生编号(pk) | 学生姓名 | 班级编号 | 班级名称 |
---|---|---|---|
1 | 张三 | 01 | 一班 |
2 | 李四 | 02 | 二班 |
3 | 王五 | 01 | 一班 |
以上表描述了班级和学生关系,显然为一对多关系(一个教室中有多个学生)
分析此表满足一范式。
因为不是复合主键,没有产生部份依赖,主键是单一主键 ,满足第二范式。
分析第三范式要求,不要产生传递依赖,但是在此表之中,一班依赖于班级编号01,班级编号01依赖于主键1,产生传递依赖,不满足三范式,下面对此表进行改进:
面对一对多表的设计可以将表拆分为两个一个学生表,一个班级表如下所示:
学生表:
学生编号(pk) | 学生姓名 | 班级编号(fk) |
---|---|---|
1 | 张三 | 01 |
2 | 李四 | 02 |
3 | 王五 | 01 |
班级表:
班级编号(pk) | 班级名称 |
---|---|
01 | 一班 |
02 | 二班 |
此时此表满足三范式 |
一对多,两张表,多的表加外键!
实践和理论上存在些许偏差,最终目的都是要完成客户需求,有的时候我们会拿冗余换取速度(sql中表和表之间的连接次数越多,效率越低)
有的时候虽然会存在数据冗余,但是为了减少连接次数,这样做也是合理的,并且利于开发人员sql语句编写难度也会降低。