范式概述
- 什么是范式?
- 为了建立冗余较小、结构合理的数据库,设计数据库时必须遵循一定的规则
在关系型数据库中这种规则就称为范式,也可以称为数据库设计范式
- 关系数据库中的关系必须满足一定的要求,即满足不同的范式。
- 范式的目的是减小数据的冗余性、提高效率
- 范式的种类
- 目前关系数据库有六种范式
第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、Boyce-Codd范式(BCNF)、第四范式(4NF)和第五范式(5NF)
- 满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多要求的称为第二范式(2NF),其余范式以次类推。
- 一般说来,数据库只需满足第三范式(3NF)即可
因此常说的数据库三大范式指的是第一范式(1NF)、第二范式(2NF)、第三范式(3NF)
1 第一范式(1NF)
- 第一范式定义
数据表的每一列都要保持它的原子特性,也就是列不能再被分割
- 实例
- 上述表就不符合第一范式规定的列原子性,不符合关系型数据库的基本要求,在关系型数据库中创建这个表的操作就不能成功。
- 将上述表改为如下形式则符合第一范式
2 第二范式(2NF)
第二范式
- 第二范式在第一范式的基础上规定数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)
- 也可以说在一个数据库表中,一个表中只能保存一类数据,不可以把多类数据保存在同一张数据库表中
实例
下面这张表以学号和课名作为联合主键,不符合第二范式的要求,因为表中的姓名、系名和系主任只与学号有关,而与课名无关
上表的缺点
- 表中的每一行数据都存储了系名、系主任,数据的冗余太大
- 如果有一个新的系还没有招到学生,那么不能将该系的信息添加到数据表中去,从数据表中看不到该系的存在
- 如果将某个系的学生信息全部删除,那么这个系在数据表里也就不存在了,但这个系实际仍存在
依赖
在数据表中,属性(属性组)X确定的情况下,能完全退出来属性Y完全依赖于X。
完全依赖
完全依赖是针对于属性组来说,当一组属性X能推出来Y的时候就说Y完全依赖于X。
部分依赖
一组属性X中的其中一个或几个属性能推出Y就说Y部分依赖于X。
结论:当一个第一范式的候选码只有一个属性的时候,那它就是第二范式(2NF)
候选码
当一个属性或者属性组确定的情况下,这张表的其余所有属性就能确定下来,这个属性或者属性组就叫做或候选码。
一张表可以有多个候选码
一般只选一个候选码作为主键
从表中找到两个属性:学号和课程
学号可以推出姓名、系名、系主任。
课程可以推出成绩。
将它们两个设置为联合主键
存在的部分依赖
- 姓名对学号存在部分依赖
- 系名对学号存在部分依赖
- 系主任对学号存在部分依赖
- 这显然不符合第二范式的要求,做出修改:
表一中分数完全依赖于学号和课程的属性
表二中姓名、系名、系主任完全依赖于学号的属性
第二范式消除了第一范式的部分依赖
3 第三范式(3NF)
- 第三范式
- 第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
- 比如在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。如下面这两个表所示的设计就是一个满足第三范式的数据库表。
这样在查询订单信息的时候,就可以使用客户编号来引用客户信息表中的记录,也不必在订单信息表中多次输入客户信息的内容,减小了数据冗余。
概念:所有的非主属性不依赖于其他的非主属性
传递函数依赖
设X,Y,Z是关系R中互不相同的属性集合,存在X→Y(Y !→X),Y→Z,则称Z传递函数依赖于X。
在改进后的学生表中:
主属性:学号
非主属性:姓名、系名、系主任
知道系名可以推出系主任,所以非主属性系主任对主属性学号存在传递函数依赖,这不符合非主属性不依赖于其它的非主属性的设计要求。将该数据表改进如下:
第三范式消除了第二范式的传递函数依赖
BC 范式
主属性不能对候选码存在部分函数依赖或者传递函数依赖
这张表不存在部分函数依赖于传递函数依赖,属于第三范式
表中的依赖关系
- 仓库名—————>管理员
- 管理员—————>仓库名
- 物品名—————>数量
主属性:仓库名、管理员、物品名
非主属性:数量
存在的问题
- 先新添加一个仓库,但尚未存放任何物品,不可以为该仓库指派管理员,因为物品名也是主属性,根据实体完整性的要求,主属性不能为空
- 某仓库被清空后,该仓库的信息也被清空
- 当需要更新仓库管理员,该仓库存放了多少物品,就要修改多少条信息。
在这个问题中就是存在了主属性对于候选码的部分依赖,也就是仓库名对于管理员和物品名的部分依赖。
修改为
仓库(仓库名,管理员)
库存(仓库名、物品数、数量)