范式
数据库规范化,又称正规化、标准化,是数据库设计的一系列原理和技术,以减少数据库中数据冗余,增进数据的一致性。关系模型的发明者埃德加·科德最早提出这一概念,并于1970年代初定义了第一范式、第二范式和第三范式的概念,还与Raymond F. Boyce于1974年共同定义了第三范式的改进范式——BC范式。
除外还包括针对多值依赖的第四范式,连接依赖的第五范式、DK范式和第六范式。
现在数据库设计最多满足3NF,普遍认为范式过高,虽然具有对数据关系更好的约束性,但也导致数据关系表增加而令数据库IO更易繁忙,原来交由数据库处理的关系约束现更多在数据库使用程序中完成。
第一范式
定义:数据库中的所有字段(列)都是单一属性,不可再分的。这个单一属性由基本的数据类型所构成,如整型、浮点型、字符串等。
第一范式是为了保证列的原子性。
学号 | 姓名 | 地址 |
---|---|---|
1001 | 陈二狗 | 北京市,海淀区,成府路,宇宙中心 |
上表不满足第一范式,其中的地址列是可以再拆分的,可以拆分成省、市、区等
学号 | 姓名 | 省 | 市 | 区 | 街道 | 门牌号 |
---|---|---|---|---|---|---|
1001 | 陈二狗 | 北京市 | 北京市 | 海淀区 | 成府路 | 宇宙中心 |
第二范式
定义:数据库中的表不存在非关键字段对任一关键字字段的部分函数依赖
部分函数依赖是指存在着组合关键字中的某一关键字决定非关键字的情况
第二范式在满足了第一范式的基础上,消除非主键列对联合主键的部分依赖
商品名称 | 供应商名称 | 价格 | 供应商电话 | 分类 |
---|---|---|---|---|
可乐 | 可乐第一制造厂 | 3.00 | 12345678 | 碳酸饮料 |
可乐 | 可乐第二制造厂 | 3.00 | 87654321 | 碳酸饮料 |
上面这张表中想要设置主键,只能是商品名称和供应商名称一起组成联合主键。但是价格和分类只依赖于商品名称,供应商电话只依赖于供应商名称,所以上面的表不满足第二范式,可以改成如下形式:
商品信息表
商品ID | 商品名称 | 价格 | 分类 |
---|---|---|---|
1001 | 可乐 | 3.00 | 碳酸饮料 |
供应商信息表
供应商ID | 供应商名称 | 联系电话 |
---|---|---|
GYS1001 | 可乐第一制造厂 | 12345678 |
GYS1002 | 可乐第二制造厂 | 87654321 |
商品-供应商关联表
商品ID | 供应商ID |
---|---|
1001 | GYS1001 |
1001 | GYS1002 |
第三范式
定义:所有非主键属性都只和候选键有相关性,也就是说非主键属性之间应该是独立无关的。
第三范式是在满足了第二范式的基础上,消除列与列之间的传递依赖。
商品名称 | 价格 | 产地 | 分类 | 分类描述 |
---|---|---|---|---|
可乐 | 3.00 | xxx | 碳酸饮料 | 肥宅快乐水 |
王老吉 | 3.00 | xxx | 凉茶 | 清凉解渴,好喝不贵 |
在上面的表中,商品的分类描述依赖分类,而分类依赖商品名称,而不是分类描述直接依赖商品名称。这样就形成了传递依赖,所以不符合第三范式。可以改成如下形式
商品表
商品名称 | 价格 | 产地 | 分类 |
---|---|---|---|
可乐 | 3.00 | xxx | 碳酸饮料 |
王老吉 | 3.00 | xxx | 凉茶 |
商品分类表
商品分类 | 分类描述 |
---|---|
碳酸饮料 | 肥宅快乐水 |
凉茶 | 清凉解渴,好喝不贵 |
数据库设计时,遵循范式和反范式一直以来是一个颇受争议的问题。遵循范式对数据关系更好的约束性,并且减少数据冗余,可以更好地保证数据一致性。而反范式则是为了获得更好地性能。所以范式还是反范式并没有明确的标准,适合自己业务场景的才是最好的。
反范式设计时,需要考虑以下几个问题,分别是插入异常、更新异常和删除异常。
- 插入异常:如果某个实体随着另一个实体的存在而存在,即缺少某个实体是无法表示这个实体,那么这个表就存在插入异常。
- 更新异常:如果更改表所对应的某个实体实例的单独属性时,需要将多行更新,那么就说明这个表存在更新异常
- 删除异常:如果删除表的某一行来表示某实体实例失效时,导致另一个不同实体实例信息丢失,那么这个表就存在删除异常
以违反第二范式的表为例,如果可乐第二制造厂这个供应商尚未开始供货,表中就不存在第二条记录,也就无法记录供应商的电话,这样就存在插入异常;如果需要把可乐的价格提高,需要更新表中的多条记录,这样就存在更新异常;如果删除可乐第二制造厂的供货信息,那么该供应商的电话也就丢失了,这样就存在删除异常。
一般存在插入异常的表,都会存在更新异常和删除异常。