目录
二十、数据库设计三大范式
定义:设计数据库的时候所依据的规范,共三个规范;
第一范式:每一张表都应该有主键,并且每一个字段都是原子性不可再分;
第二范式:所有的非主键字段应该完全依赖主键,不能产生部分依赖;
第三范式:所有的非主键字段应该直接依赖主键,不能产生传递依赖;
结论:数据库设计尽量遵循三范式,但是还是要根据实际情况进行取舍,有时可能会拿冗余
换速度,最终目的满足客户需求。
1)第一范式:主键、字段不能再分
定义:要求有主键,数据库中不能出现重复记录,每一个字段是原子性不能再分;
示例:不符合第一范式
学生编号 |
学生姓名 |
联系方式 |
1001 |
张三 |
zhangsan@gmail.com,1351254 |
1002 |
李四 |
lisi@gmail.com,1351255 |
1001 |
王五 |
wangwu@gmail.com,1351256 |
分析以上存在的问题:
1)数据存在重复记录,数据不唯一,没有主键;
2)联系方式可以再分,不是原子性;
修改以上设计方案:
学生编号(pk) |
学生姓名 |
联系方式 |
|
1001 |
张三 |
zhangsan@gmail.com |
1351254 |
1002 |
李四 |
lisi@gmail.com |
1351255 |
1003 |
王五 |
Wangwu@gmail.com |
1351256 |
1. 每一行必须唯一,也就是每个表必须有主键。
2. 主键主要通过采用数值型或定长字符串表示。
3. 关于列不可再分,应该根据具体情况来决定。
2)第二范式:非主键字段完全依赖主键
定义:建立在第一范式基础之上,要求数据库中所有非主键字段完全依赖主键,不能产生部
分依赖。
示例:确定主键,学生编号,教师编号,出现冗余
学生编号(pk) |
教师编号(pk) |
学生姓名 |
教师姓名 |
1001 |
001 |
张三 |
王老师 |
1002 |
002 |
李四 |
赵老师 |
1003 |
001 |
王五 |
王老师 |
1001 |
002 |
张三 |
赵老师 |
综合分析:
1. 以上虽然确定了主键,但此表出现大量冗余,主要涉及到的冗余字段为“学生姓名”和
“教师姓名”。
2. 出现冗余的原因:学生姓名部分依赖了主键的一个字段学生编号,而没有依赖教师编
号,而教师姓名部分依赖了主键的教师编号,这就是第二范式部分依赖。
解决方案:
学生信息表:
学生编号(pk) |
学生姓名 |
1001 |
张三 |
1002 |
李四 |
1003 |
王五 |
教师信息表:
教师编号(pk) |
教师姓名 |
001 |
王老师 |
002 |
赵老师 |
教师和学生的关系表:
学生编号(pk)fk->学生表的学生编号 |
教师编号(pk)fk->教师表的教师编号 |
1001 |
001 |
1002 |
002 |
1003 |
001 |
1001 |
002 |
结论:典型“多对多”的设计。
3)第三范式:非主键字段直接依赖主键
定义:建立在第二范式基础之上,要求非主键字段不能产生传递依赖于主键字段;
示例:学生信息表
学生编号(pk) |
学生姓名 |
班级编号 |
班级名称 |
1001 |
张三 |
01 |
一年一班 |
1002 |
李四 |
02 |
一年二班 |
1003 |
王五 |
03 |
一年三班 |
1004 |
田六 |
03 |
一年三班 |
综合分析:
1. 从表中看出,班级名称字段存在冗余,因为班级名称字段没有完全依赖主键。
2. 班级名称字段依赖于班级编号,班级编号依赖于学生编号,那么这就是传递依赖。
解决方案:
1. 将冗余字段单独拿出来建立表;
2. 学生信息表中班级编号设为外键fk
学生信息表:
学生编号(pk) |
学生姓名 |
班级编号(fk) |
1001 |
张三 |
01 |
1002 |
李四 |
02 |
1003 |
王五 |
03 |
1004 |
田六 |
03 |
班级信息表:
班级编号(pk) |
班级名称 |
01 |
一年一班 |
02 |
一年二班 |
03 |
一年三班 |
结论:典型“一对多”的设计,一(班级表)存储在一张表中,多(学生表)存储在一张表中,在多
(学生表)的那张表中添加外键指向一(班级表)的一方的主键。
4)三范式总结(经典的设计)
1. 一对一:分两张表存储,共享主键。
2. 一对多:分两张表,外键唯一。
3. 多对多:分三张表存储,各自存储自己的信息。
5)实际开发中咋样处理?
1. 数据库设计尽量遵循三范式。
2. 根据实际需求进行取舍,有时间可能会拿冗余换速度,最终满足客户需求。