目前关系数据库有六种范式:
第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般说来,数据库只需满足第三范式(3NF)就行了。所以这里就只记录三范式相关的知识。
三范式
1NF:字段不可分;
2NF:有主键,非主键字段依赖主键;
3NF:非主键字段不能相互依赖;
解释:
1NF:原子性 字段不可再分,否则就不是关系数据库;
2NF:唯一性 一个表只说明一个事物;
3NF:每列都与主键有直接关系,不存在传递依赖;
第一范式(1NF)
即表的列的具有原子性,不可再分解,即列的信息,不能分解, 只要数据库是关系型数据库(mysql/oracle/db2/informix/sysbase/sql server),就自动的满足1NF。数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。如果实体中的某个属性有多个值时,必须拆分为不同的属性 。通俗理解即一个字段只存储一项信息。
关系型数据库: mysql/oracle/db2/informix/sysbase/sql server
非关系型数据库: (特点: 面向对象或者集合)
NoSql数据库: MongoDB/redis(特点是面向文档)
数据表的每一列都要保持它的原子特性,也就是列不能再被分割。
这张表就不符合第一范式规定的原子性,不符合关系型数据库的基本要求,在关系型数据库中创建这个表的操作就不能成功。不得不将数据表设计为如下形式。
第二范式(2NF)
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被惟一地区分。为实现区分通常需要我们设计一个主键来实现(这里的主键不包含业务逻辑)。
即满足第一范式前提,当存在多个主键的时候,才会发生不符合第二范式的情况。比如有两个主键,不能存在这样的属性,它只依赖于其中一个主键,这就是不符合第二范式。通俗理解是任意一个字段都只依赖表中的同一个字段。(涉及到表的拆分)
概率:属性必须完全依赖于主键。
下满这张表不符合第二范式的要求。
缺点
- 表中的第一行数据都存储了系名、系主任,数据的冗余太大
- 如果有一个新的系还没有开始找到学生,那么不能讲该系的信息添加到数据表中去,从数据表中看不到该系的存在
- 如果将某个系的学生信息全部删除,那么这个系在数据表里也就不存在了,但这个系还存在。
- 如果某个人要转系,那么为了保证数据库中数据的一致性,需要修改三条记录中系与系主任的数据
依赖
在数据表中,属性(属性组)X确定的情况下,能完全退出来属性Y完全依赖于X。
完全依赖
完全依赖是针对于属性组来说,当一组属性X能推出来Y的时候就说Y完全依赖于X。
部分依赖
一组属性X中的其中一个或几个属性能推出Y就说Y部分依赖于X。
结论:当一个第一范式的候选码只有一个属性的时候,那它就是第二范式(2NF)
候选码
当一个属性或者属性组确定的情况下,这张表的其余所有属性就能确定下来,这个属性或者属性组就叫做或候选码。
一张表可以有多个候选码
一般只选一个候选码作为主键
从表中找到两个属性:学号和课程
学号可以推出姓名、系名、系主任。
课程可以推出成绩。
将它们两个设置为联合主键
存在的部分依赖
- 姓名对学号存在部分依赖
- 系名对学号存在部分依赖
- 系主任对学号存在部分依赖
- 这显然不符合第二范式的要求,做出修改:
表一中分数完全依赖于学号和课程的属性
表二中姓名、系名、系主任完全依赖于学号的属性
第二范式消除了第一范式的部分依赖
第三范式(3NF)
满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主键字段。就是说,表的信息,如果能够被推导出来,就不应该单独的设计一个字段来存放(能尽量外键join就用外键join)。很多时候,我们为了满足第三范式往往会把一张表分成多张表。
即满足第二范式前提,如果某一属性依赖于其他非主键属性,而其他非主键属性又依赖于主键,那么这个属性就是间接依赖于主键,这被称作传递依赖于主属性。 通俗解释就是一张表最多只存两层同类型信息。
概念:所有的非主属性不依赖于其他的非主属性
传递函数依赖
设X,Y,Z是关系R中互不相同的属性集合,存在X→Y(Y !→X),Y→Z,则称Z传递函数依赖于X。
在改进后的学生表中:
主属性:学号
非主属性:姓名、系名、系主任
知道系名可以推出系主任,所以非主属性系主任对主属性学号存在传递函数依赖,这不符合非主属性不依赖于其它的非主属性的设计要求。将该数据表改进如下:
第三范式消除了第二范式的传递函数依赖
BC 范式
主属性不能对候选码存在部分函数依赖或者传递函数依赖
这张表不存在部分函数依赖于传递函数依赖,属于第三范式
表中的依赖关系
- 仓库名—————>管理员
- 管理员—————>仓库名
- 物品名—————>数量
主属性:仓库名、管理员、物品名
非主属性:数量
存在的问题
- 先新添加一个仓库,但尚未存放任何物品,不可以为该仓库指派管理员,因为物品名也是主属性,根据实体完整性的要求,主属性不能为空
- 某仓库被清空后,该仓库的信息也被清空
- 当需要更新仓库管理员,该仓库存放了多少物品,就要修改多少条信息。
在这个问题中就是存在了主属性对于候选码的部分依赖,也就是仓库名对于管理员和物品名的部分依赖。
修改为
仓库(仓库名,管理员)
库存(仓库名、物品数、数量)
范式的目的
- 减小数据的冗余性
- 提高效率
反三范式
没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,提高读性能,就必须降低范式标准,适当保留冗余数据。具体做法是: 在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,减少了查询时的关联,提高查询效率,因为在数据库的操作中查询的比例要远远大于DML的比例。但是反范式化一定要适度,并且在原本已满足三范式的基础上再做调整的。
摘自: