一. 数据库设计范式
1.1 何为范式
简言之就是,数据库设计对数据的存储性能,还有开发人员对数据的操作都有莫大的关系。所以建立科学的,规范的的数据库是需要满足一些规范的来优化数据数据存储方式。在关系型数据库中这些规范就可以称为范式。
1.2 理解范式前的基本概念准备
实体:现实世界中客观存在并可以被区别的事物。比如“一个学生”、“一本书”、“一门课”等等。值得强调的是这里所说的“事物”不仅仅是看得见摸得着的“东西”,它也可以是虚拟的,比如说“老师与学校的关系”。
属性:教科书上解释为:“实体所具有的某一特性”,由此可见,属性一开始是个逻辑概念,比如说,“性别”是“人”的一个属性。在关系数据库中,属性又是个物理概念,属性可以看作是“表的一列”。
元组:表中的一行就是一个元组。
分量:元组的某个属性值。在一个关系数据库中,它是一个操作原子,即关系数据库在做任何操作的时候,属性是“不可分的”。否则就不是关系数据库了。
码:表中可以唯一确定一个元组的某个属性(或者属性组),如果这样的码有不止一个,那么大家都叫候选码,我们从候选码中挑一个出来做老大,它就叫主码。
全码:如果一个码包含了所有的属性,这个码就是全码。
主属性:一个属性只要在任何一个候选码中出现过,这个属性就是主属性。
非主属性:与上面相反,没有在任何候选码中出现过,这个属性就是非主属性。
外码:一个属性(或属性组),它不是码,但是它别的表的码,它就是外码。
1.2 范式分类
- 第一范式:当关系模式R的所有属性都不能再分解为更基本的数据单位时,称R是满足第一范式的,简记为1NF。满足第一范式是关系模式规范化的最低要求,否则,将有很多基本操作在这样的关系模式中实现不了。
- 第二范式:如果关系模式R满足第一范式,并且R的所有非主属性都完全依赖于R的每一个候选关键属性,称R满足第二范式,简记为2NF。
- 第三范式:设R是一个满足第一范式条件的关系模式,X是R的任意属性集,如果X非传递依赖于R的任意一个候选关键字,称R满足第三范式,简记为3NF.
note:关系实质上是一张二维表,其中每一行是一个元组,每一列是一个属性
二. 第一范式
数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。(保持数据的原子性)
数据原子性很好理解,就是表中的字段不可再分。符合数据库第一范式的表,每个字段表意明确,看个例子:
这是一张简单的员工信息表,其中有工号、姓名、电话三个字段。通过电话这个字段获得的信息有可能是家庭电话,或是工作地点的电话,或是手机,因此表达的信息并不明确,我们可以改成这样:
经过修改,表格的含义就很清晰了。
三. 第二范式
在满足第一范式的基础上,实体的每个非主键属性完全函数依赖于主键属性(消除部分依赖)。满足1NF后,要求表中的所有列,都必须依赖于主键,而不能有任何一列与主键没有关系,也就是说一个表只描述一件事情,这就是第二范式。
依赖:对于X的每个值,Y都有一个值与之对应,反过来则不一定不成立,这叫做X函数决定Y,Y函数依赖X(X往往是主键)。
还拿上面的那张表举来说,对于每个工号,都有一个姓名与之对应,即工号决定姓名,姓名依赖工号;但由于员工之间可能有重名,一个姓名可能对应多个工号,所以姓名不能决定工号。
部分依赖:当主键由两个或两个以上字段构成,而表中的某些信息通过主键的一个字段就能唯一确定,我们称这样的依赖关系为部分依赖,比如这个例子:
学生选课(学号,姓名,专业,课程号,课程名,成绩),该表中一个学生可以选多门课,一门课有多个学生。学号和课程号可以唯一确定一条记录,因此用学号和课程号做主键。
表中的姓名、专业通过主键中的学号就能唯一确定,而课程名通过课程号唯一确定,这就是部分依赖,这样的设计不符合第二范式。
不符合第二范式会带来哪些问题呢?
1、数据信息冗余,可见上表
2、增删改会出现问题,比如有一门《操作系统》没有人选,那么由于缺少学号(主键之一)那么这门课就不能出现在表里。
如何解决呢,我们可以用关系分解的方法消除部分依赖,将上表改成如下三张表:
再比如:
订单表只描述订单相关的信息,所以所有字段都必须与订单id相关
产品表只描述产品相关的信息,所以所有字段都必须与产品id相 关;
因此不能在一张表中同时出现订单信息与产品信息;如下图所示:
四. 第三范式
必须先满足第二范式(2NF),要求:表中的每一列只与主键直接相关而不是间接相关,(表中的每一列只能依赖于主键);这就是第三范式。
传递依赖:A依赖于B,B依赖于C,就可以说A依赖C。看这样一张表:
这张表中有如下决定关系: 学号-->姓名,性别,系号-->决定系名,宿舍号-->决定宿舍电话,也有 学号-->系名,学号-->宿舍电话。
在这样一张表中则存在着传递依赖。也就是系名依赖系号,系号依赖学号,那么间接的系名依赖学号,宿舍号、宿舍电话和学号之间也有同样的关系。这样设计表的同样会带来数据冗余,操作异常等问题。那么我们同样可以用关系分解的分解的方法来消除传递依赖,将这张表分成三张表:
这就是数据可设计的三范式了。
再比如:
订单表中需要有客户相关信息,在分离出客户表之后,订单表中只需要有一个用户id即可,而不能有其他的客户信息。因为其他的客户信息直接关联于用户id,而不是直接与订单id直接相关。