为什么会有“三范式”?
数据库的三范式是为了设计更为合理数据库表结构,从而提高数据存储和使用的性能。
哪“三范式”?
答:第一范式、第二范式、第三范式。
当然除了三范式之外还有“巴斯-科德范式”(BC范式)、第四范式、第五范式。
本文着重介绍第一、第二、第三范式。
所有高级别的范式都是在低级别的范式之上建立的,也就是说第二范式必然是满足第一范式的;满足第三范式的必然是满足第二、第一范式的。
第一范式(1NF)
满足原子性,即表中字段的数据不可再拆分
先看一个不满足第一范式的表:
用户编号 | 用户名 | 密码 |
---|---|---|
1 | 上海市张三 | 123456 |
2 | 浙江省李四 | 123123 |
3 | 江苏省王德发 | 456456 |
为什么这个表不满足第一范式呢?很明显用户名字段不是原子的,也就是可以再拆分,可以将省份拆出来。
用户编号 | 用户名 | 密码 | 地址 |
---|---|---|---|
1 | 张三 | 123456 | 上海市 |
2 | 李四 | 123123 | 浙江省 |
3 | 王德发 | 456456 | 江苏省 |
将用户名字段中的地址拆分成单独的一列,现在表中所有字段的数据都不可以再拆分,满足第一范式。
第二范式(2NF)
在满足第一范式的前提下,遵循唯一性,消除部分依赖;即表中任意一个主键或者任意一组联合主键,可以确定除该主键外的所有非主键值
再通俗讲,就是一个表只描述一件事。
先看一个不满足第二范式的表:
用户编号 | 用户名 | 密码 | 科目 | 成绩 |
---|---|---|---|---|
1 | 张三 | 123456 | 数学 | 98 |
2 | 李四 | 123123 | 语文 | 98 |
3 | 王德发 | 456456 | 数学 | 76 |
为什么这个表不满足第二范式呢?假如用户编号是主键,通过用户编号可以唯一确定用户名和密码,但是却不能确定科目和成绩,科目中数学是重复的,成绩98是重复的。可以将课程和成绩拆分出来,分别描述课程和成绩。
用户表
用户编号 | 用户名 | 密码 |
---|---|---|
1 | 张三 | 123456 |
2 | 李四 | 123123 |
3 | 王德发 | 456456 |
课程表
课程编号 | 课程名称 |
---|---|
1 | 语文 |
2 | 数学 |
成绩表
用户编号 | 课程编号 | 成绩 |
---|---|---|
1 | 语文 | 98 |
2 | 数学 | 98 |
3 | 数学 | 76 |
这样每个表都能清楚的描述一件事,满足第二范式。
第三范式(3NF)
在满足第二范式的前提下,消除依赖传递;即在任意主键都可以确定非主键值的情况下,不能存在通过某非主键字段A还可以获取到某非主键字段B
先看一个不满足第三范式的表:
用户编号 | 用户名 | 密码 | 班级 | 班主任 |
---|---|---|---|---|
1 | 张三 | 123456 | 1班 | 汪老师 |
2 | 李四 | 123123 | 2班 | 张老师 |
为什么这个表不满足第三范式呢?假如用户编号是主键,其余都是非主键。首先通过用户编号可以唯一确定用户名、 密码、班级、班主任;满足第二范式,没有可拆分字段值,满足第一范式,但是通过“1班”可以唯一确定班主任就是汪老师;通过张老师就可以唯一确定是“2班”;存在传递依赖,不满足第三范式。
再拆分一张班级表。
用户表
用户编号 | 用户名 | 密码 |
---|---|---|
1 | 张三 | 123456 |
2 | 李四 | 123123 |
班级表
班级名称 | 班主任 |
---|---|
1班 | 汪老师 |
2班 | 张老师 |
这样就可以消除依赖,满足第三范式。
总结
第一范式(1NF):字段不可再拆分
第二范式(2NF):表中任意一个主键或者任意一组联合主键,可以确定除该主键外的所有非主键值
第三范式(3NF):在任意主键都可以确定非主键值的情况下,不能存在通过某非主键字段A还可以获取到某非主键字段B