三大范式
第一范式(所有字段不可拆分)
违反第一范式
姓名 | 年龄 | 居住地 |
---|---|---|
张三 | 17 | 浙江省宁波市 |
李四 | 20 | 江苏省无锡市 |
所有的字段都是不可拆分的,这里的居住地字段就可以接着拆分为居住地省,居住地市
改进
姓名 | 年龄 | 居住地省 | 居住地市 |
---|---|---|---|
张三 | 17 | 浙江省 | 宁波市 |
李四 | 20 | 江苏省 | 无锡市 |
第二范式(字段需依赖主键中的全部信息,而不能只依赖部分信息)
这里的主键是理解为姓名 + 订单号
姓名 | 年龄 | 居住地省 | 居住地市 | 淘宝订单号 | 商品 |
---|---|---|---|---|---|
张三 | 17 | 浙江省 | 宁波市 | 123X | 牙刷 |
李四 | 20 | 江苏省 | 无锡市 | 456X | 拖鞋 |
所有的字段都是依赖于主键中的全部信息的,这里的商品信息则是依赖于订单号的,而其他信息均依赖于姓名,所以在设计的时候,将订单号作为用户表的外键,订单表的主键,设计一张订单表,和用户表进行关联
个人信息表
姓名 | 年龄 | 居住地省 | 居住地市 | 淘宝订单号 | 商品 |
---|---|---|---|---|---|
张三 | 17 | 浙江省 | 宁波市 | 123X | 牙刷 |
李四 | 20 | 江苏省 | 无锡市 | 456X | 拖鞋 |
订单信息表
淘宝订单号 | 商品 |
---|---|
123X | 牙刷 |
456X | 拖鞋 |
第三范式(确保每列都是和主键直接相关,而不是间接相关的)
这里主键是姓名,且所有的字段都可以是完全依赖主键中的全部信息的
姓名 | 年龄 | 居住地省 | 居住地市 | 居住地邮政编码 |
---|---|---|---|---|
张三 | 17 | 浙江省 | 宁波市 | 31500 |
李四 | 20 | 江苏省 | 无锡市 | 21400 |
但是这里的邮政编码和主键的关系存在 姓名 -> 居住地市 -> 邮政编码,所以在数据库涉及的时候,我们可以把居住地市作为一个外键,设计一张区域信息表,和用户信息表关联。
用户信息表
姓名 | 年龄 | 居住地省 | 居住地市 |
---|---|---|---|
张三 | 17 | 浙江省 | 宁波市 |
李四 | 20 | 江苏省 | 无锡市 |
区域信息表
居住地市 | 居住地邮政编码 |
---|---|
宁波市 | 31500 |
无锡市 | 21400 |
2NF和3NF均涉及到了主键和非主键之间的关联关系,一开始确实不好理解。私以为,2NF解决的问题比较像是一张表中不能存储两种信息,如用户表中又存储了订单信息,而3NF解决的问题是不能存储其中某个字段的扩展信息,如用户表中本来存了居住地,但是又增加存储了一些居住地的相关信息像是邮政编码等。
介绍完三大范式我们也来说一说一些关于范式以及反范式的优缺点
遵循范式的优点
- 分离出来的表更小
- 可以减少重复的数据,更新时只需要更新比较少的数据
- 更新操作更快
遵循范式的缺点
- 在进行一些比较复杂的更新搜索的时候,需要对许多张表进行关联,会增加查询的代价
反范式的优点
- 查询更简单(不需要多表关联)
- 索引设计更简单(不需要多表关联)
反范式的缺点
- 进行一些更新删除操作时由于数据并非存在一张表中,可能会造成数据不同步。