范式是指数据表设计的基本原则、规则。范式存在不同的等级,不同等级之间是层层递进的,如满足了第二范式就一定满足了第一范式。范式的等级越高,数据的冗余程度越低,适合在增删改更多的场景下,用来保证数据的一致性,更适合OLTP型任务;但在复杂数据查询中所要join的表就越多,数据查询的性能就越低,不适合OLAP型任务。
一、前置知识——键和属性
假设有两个表:
球员表:球员编号|姓名|身份证号|年龄|球队编号
球队表:球队编号|主教练|球队所在地
(1)超键:能够唯一标识一条数据,如对于球员表来说,(球员编号),(球员编号,姓名),(球员编号,姓名,身份证)... 都能够用来唯一标识一条球员数据。
(2)候选键:最小的超键,对于球员表来说,(球员编号),(身份证号)都是候选键
(3)主键:从候选键中选一个。
(4)外键:某个字段是其他数据表的主键,如球员表中的球队编号对于球员表来说就是外键。
(5)主属性、非主属性:候选键中的字段,如对球员表来说,球员编号,省份证号都是主属性,其余都是非主属性。
二、第一范式(1NF)
要求属性字段是不可拆分的,具有原子性。
如一下订单表不符合1NF,商品字段不满足原子性,应该拆分为数量和商品两个字段:
ID | 商品 | 商品ID | 用户ID |
001 | 5台电脑 | XXX旗舰店 | 00001 |
三、第二范式(2NF)
只能存在完全函数依赖,不能存在部分函数依赖。即非主属性字段只能完全依赖于主键,不能只依赖于主键的一部分。
如以下学生成绩表:
学号 | 姓名 | 系名 | 系主任 | 课名 | 分数 |
001 | 张三 | 计算机 | 李四 | MySQL | 99 |
主键是(学号,课名),只有分数是完全由这一主键所决定的(完全依赖),而姓名、系名、系主任都可以由学号唯一确定(部分依赖),因此不符合2NF。为符合2NF,要拆成学生表和成绩表两个表如下:
学号 | 课名 | 分数 |
001 | MySQL | 99 |
学号 | 姓名 | 系名 | 系主任 |
001 | 张三 | 计算机 | 李四 |
四、第三范式(3NF)
不能存在传递依赖。即非主属性字段只能直接依赖于主键,不能传递依赖于主键。
如上面的学生表,系名直接依赖于学号,而系主任直接依赖于系名,通过系名传递依赖于学号,不符合3NF。应继续拆分成学生表和院系表。
五、BCNF范式
在3NF的基础上消除了主属性对候选键的部份依赖或传递依赖关系。