数据库范式
数据库的设计范式是数据库设计所需要满足的规范,满足这些规范的数据库是简洁的、结构明晰的,同时,不会发生插入(insert)、删除(delete)和更新(update)操作异常。
反之则是乱七八糟,不仅给数据库的编程人员制造麻烦,而且面目可憎,可能存储了大量不需要的冗余信息。
1.若将所有的信息放在一个表中,存在的问题:
现在建立一个描述学校教务的数据库,该数据库涉及的对象包括学生的学号(Sno),所在系(Sdept),
系主任姓名(Mname),课程号(Cno)和成绩(Grade)。假设用一个单一的关系模式Student来表示,
则该关系模式的属性集合为:
U={Sno,Sdept,Mname,Cno,Grade}
存在的问题:
数据冗余过大。造成大量的存储空间。(比如在相同的系的各个学号均包含相同的系主任名称)
更新复杂。(比如修改系主任名称,需要修改多行)
插入异常:如果一个系刚成立,尚无学生,就无法将这个系及其系主任存入数据库。
删除异常:如果某个系的学生全部毕业了,删除该系学生信息的同时,把这个系及其系主任的信息也去掉了。
概念:
关系:指包含具体数据的一张具体 表。
关系模式:指表的定义,包含哪些列,及列之间的相互依赖关系等等。是属于一种场景的语义描述。
R(U),R是指的关系模式,U是关系模式上列的集合,X,Y是U的子集。即X,Y是一些列的集合。
函数依赖:如果知道X的值,就一定知道Y的值。记作X->Y。如知道学生的学号,就一定知道学生的姓名。这属于函数依赖。
完全函数依赖:如果x->y,且对于x的任何一个子集x',都有x'不能推导出y,则称y对x完全函数依赖。
比如知道学号及学号对应的系,可以知道学生姓名,这属于部分函数依赖,因为知道学号,就可以知道学生姓名。
部分函数依赖:如果x->y,但y不完全函数依赖于x,则y对于x部分函数依赖。
传递函数依赖:
x->y,y不是x的子集,y不能推导出x,y->z,则称z是x的传递函数依赖。
非平凡的函数依赖:x->y,但y不属于x的子集,是非平凡的函数依赖。
平凡的函数依赖:x->y,且y属于x,则称x->y是平凡的函数依赖。
码:
R<U,F>
U为列的集合,F为函数依赖x
设K为R<U,F>中的属性或者属性集合(即K是一个列或几个列的组合),若K能完全推导出U,
且K的每个子集均不能推导出U,则K为R的候选码(Candidate Key),简称为码。若候选码多于一个,
则选定其中一个为主码。(Primary key)。
包含在任何一个候选码中的属性,称为主属性,不包含在任何码中的属性称为非主属性,
或非码属性。最简单个情况,单个属性是码,极端的情况,整个属性是码.
第一范式(1NF):
列是同质的(即每一个列是同一类型的数据)
不同的列可以出自于同一个域(域即数据类型),不同的属性要给与不同的属性名。
列的顺序无所谓,即列的次序可以任意交换。
任意的两个元组不能相同(即不能存在重复行)
行的顺序无所谓,即行的次序可以任意交换。
分量必须取原子值,即每一个分量都必须是不可分的数据项。
第二范式:
首选满足于第一范式。
且每一个非主属性完全函数依赖于码,即属于第二范式。
第三范式
每一个非主属性不传递依赖于码。
来自于百科介绍:
第一范式:
数据库表的每一列都是不可分割的基本数据项,同一列不能有多个值。
第二范式:
表中每一行必须被唯一的区分,这个唯一属性列被称为主关键字,或者主键,主码。
第二范式要求实体的属性完全依赖于主属性。所谓完全依赖就是指不能存在仅依赖主关键字一部分的属性。
第三范式:
属性不依赖于其他非主属性。
或者说要求一个数据库表中不包含已在其他表中已包含的非主关键字信息。
1.4 鲍依斯-科得范式(BCNF是3NF的改进形式)
若关系模式R是第一范式,且每个属性都不传递依赖于R的候选键。这种关系模式就是BCNF模式。即在第三范式的基础上,数据库表中如果不存在任何字段对任一候选关键字段的传递函数依赖则符合鲍依斯-科得范式。
假设仓库管理关系表为StorehouseManage(仓库ID, 存储物品ID, 管理员ID, 数量),且有一个管理员只在一个仓库工作;一个仓库可以存储多种物品。这个数据库表中存在如下决定关系:
(仓库ID, 存储物品ID) →(管理员ID, 数量)
(管理员ID, 存储物品ID) → (仓库ID, 数量)
所以,(仓库ID, 存储物品ID)和(管理员ID, 存储物品ID)都是StorehouseManage的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:
(仓库ID) → (管理员ID)
(管理员ID) → (仓库ID)
即存在关键字段决定关键字段的情况,所以其不符合BCNF范式。它会出现如下异常情况:
(1) 删除异常:
当仓库被清空后,所有"存储物品ID"和"数量"信息被删除的同时,"仓库ID"和"管理员ID"信息也被删除了。
(2) 插入异常:
当仓库没有存储任何物品时,无法给仓库分配管理员。
(3) 更新异常:
如果仓库换了管理员,则表中所有行的管理员ID都要修改。
把仓库管理关系表分解为二个关系表:
仓库管理:StorehouseManage(仓库ID, 管理员ID);
仓库:Storehouse(仓库ID, 存储物品ID, 数量)。
这样的数据库表是符合BCNF范式的,消除了删除异常、插入异常和更新异常。
四种范式之间存在如下关系: