关系型数据库三范式,可以理解成:
1、第一范式:每个键值独立
反义:值不独立
2、第二范式:只能依赖主键全部
反义:依赖部分主键
3、第三范式:唯一依赖主键
反义:依赖了其它键,包含依赖主键和其他键+仅依赖其他键盘
第一范式容易理解。
第二范式,对于只有一个主键的表来说,当非主键依赖主键时,就满足第二范式。
如果有多个主键,当非主键依赖全部主键的组合产生条件,也满足第二范式。
第三范式:非主键只能依赖主键,不可依赖其他键。
第一、二、三范式不是完全递进关系。
第一范式不满足,可以满足第二、三范式。
第二范式不满足,可以满足第三范式。
不满足范式产生后果:
微观层面看从增删查改四个方面来看影响,具体从功能和性能两个维度。
宏观层面看,造成表不简洁,不优雅,不明晰。
不满足第一范式:
ID | email-content |
1 | 我去了天津的金宝公司501房 |
2 | 海雷公司在北京市 |
我想把我去了天津改成北京,必须找到1,然后编程搜索替换天津市。
不满足第二范式:
下表中(学号
,课程
)组合起来作为主键,可以发现,分数
是依赖于全部主键的,而姓名
仅仅依赖于学号
,和课程
没有关系,这就叫部分依赖,不满足第二范式。
学号(primary key) | 课程(primary key) | 分数 | 姓名 |
1 | 语文 | 90 | 想想 |
1 | 数学 | 90 | 想想 |
1 | 英语 | 90 | 想想 |
2 | 语文 | 100 | 涵涵 |
2 | 数学 | 100 | 涵涵 |
2 | 英语 | 100 | 涵涵 |
3 | 语文 | 95 | 宇宇 |
3 | 数学 | 95 | 宇宇 |
3 | 英语 | 95 | 宇宇 |
改为正常满足第二范式设计:
ID | 课程 | 分数 |
1 | 语文 | 90 |
1 | 数学 | 90 |
1 | 英语 | 90 |
2 | 语文 | 100 |
2 | 数学 | 100 |
2 | 英语 | 100 |
3 | 语文 | 95 |
3 | 数学 | 95 |
3 | 英语 | 95 |
ID | 姓名 |
1 | 想想 |
2 | 涵涵 |
3 | 宇宇 |
不满足第二范式会存在一些问题:
-
数据冗余:按每个记录相同,前者40个存贮单位,后者38
-
删除异常:删除所有学生成绩,课程信息不得不也一起删除
-
插入异常:新来一个同学,未参加考试不知道分数,想先登记名字,结果无法插入,只能乱写个科目,分数随便写一个
不满足第三范式:
下表中学号为主键,但是学院电话字段不依赖序号,依赖所在学院,因此违反了第三范式。
学号 | 姓名 | 年龄 | 所在学院 | 学院电话 |
1 | 张三 | 10 | 文学院 | 01012345678 |
2 | 李四 | 12 | 理学院 | 02087654321 |
修正后:
学号 | 姓名 | 年龄 | 所在学院 |
1 | 张三 | 10 | 文学院 |
2 | 李四 | 12 | 理学院 |
序号 | 学院名 | 学院电话 |
1 | 文学院 | 01012345678 |
2 | 理学院 | 02087654321 |
违反后果:
单纯的想增加一个学院及其电话还不行。
想修改文学院电话还得表里所有的都更新。
其他:
为了满足特定需求,可以违反数据库范式设计原则。
比如历史订单,可以把购物者地址全部存在一起,这样反而方便。否则比如某个地址被更新了,实际购买地址也要一起更新。