数据库函数依赖及范式(最通俗易懂)
⼀、基础概念
要理解范式,⾸先必须对知道什么是关系数据库,如果你不知道,我可以简单的不能再简单的说⼀下:关系数据库就是⽤⼆维表来保存数据。表和表之间可以……(省略10W字)。
然后你应该理解以下概念:
实体:现实世界中客观存在并可以被区别的事物。⽐如“⼀个学⽣”、“⼀本书”、“⼀门课”等等。值得强调的是这⾥所说的“事物”不仅仅是看得见摸得着的“东西”,它也可以是虚拟的,不如说“⽼师与学校的关系”。
属性:教科书上解释为:“实体所具有的某⼀特性”,由此可见,属性⼀开始是个逻辑概念,⽐如说,“性别”是“⼈”的⼀个属性。在关系数据库中,属性⼜是个物理概念,属性可以看作是“表的⼀列”。
元组:表中的⼀⾏就是⼀个元组。
分量:元组的某个属性值。在⼀个关系数据库中,它是⼀个操作原⼦,即关系数据库在做任何操作的时候,属性是“不可分的”。否则就不是关系数据库了。
码:表中可以唯⼀确定⼀个元组的某个属性(或者属性组),如果这样的码有不⽌⼀个,那么⼤家都叫候选码,我们从候选码中挑⼀个出来做⽼⼤,它就叫主码。
全码:如果⼀个码包含了所有的属性,这个码就是全码。
主属性:⼀个属性只要在任何⼀个候选码中出现过,这个属性就是主属性。
⾮主属性:与上⾯相反,没有在任何候选码中出现过,这个属性就是⾮主属性。
外码:⼀个属性(或属性组),它不是码,但是它别的表的码,它就是外码。
⼆、6个范式
好了,上⾯已经介绍了我们掌握范式所需要的全部基础概念,下⾯我们就来讲范式。⾸先要明⽩,范式的包含关系。⼀个数据库设计如果符合第⼆范式,⼀定也符合第⼀范式。如果符合第三范式,⼀定也符合第⼆范式…
第⼀范式(1NF):属性不可分。
在前⾯我们已经介绍了属性值的概念,我们说,它是“不可分的”。⽽第⼀范式要求属性也不可分。那么它和属性值不可分有什么区别呢?给⼀个例⼦:
name tel age
⼤宝136****567822
⼩明139****6655010-123456721
Ps:这个表中,属性值“分”了。
name tel
age ⼿机座机
⼤宝136****5678021-987654322
⼩明139****6655010-123456721
Ps:这个表中,属性 “分”了。
这两种情况都不满⾜第⼀范式。不满⾜第⼀范式的数据库,不是关系数据库!所以,我们在任何关系数据库管理系统中,做不出这样
的“表”来。(也就是说,只要是关系数据库就是第⼀范式)
第⼆范式(2NF):符合1NF,并且,⾮主属性完全依赖于码。
听起来好像很神秘,其实真的没什么。
⼀个候选码中的主属性也可能是好⼏个。如果⼀个主属性,它不能单独做为⼀个候选码,那么它也不能确定任何⼀个⾮主属性。给⼀个反例:我们考虑⼀个⼩学的教务管理系统,学⽣上课指定⼀个⽼师,⼀本教材,⼀个教室,⼀个时间,⼤家都上课去吧,没有问题。那么数据库怎么设计?(学⽣上课表)
学⽣课程⽼师⽼师职称教材教室上课时间
⼩明⼀年级语⽂(上)⼤宝副教授《⼩学语⽂1》10114:30
⼀个学⽣上⼀门课,⼀定在特定某个教室。所以有(学⽣,课程)->教室
⼀个学⽣上⼀门课,⼀定是特定某个⽼师教。所以有(学⽣,课程)->⽼师
⼀个学⽣上⼀门课,他⽼师的职称可以确定。所以有(学⽣,课程)->⽼师职称
⼀个学⽣上⼀门课,⼀定是特定某个教材。所以有(学⽣,课程)->教材
⼀个学⽣上⼀门课,⼀定在特定时间。所以有(学⽣,课程)->上课时间
因此(学⽣,课程)是⼀个码。数据库简单吗
然⽽,⼀个课程,⼀定指定了某个教材,⼀年级语⽂肯定⽤的是《⼩学语⽂1》,那么就有课程->教材。(学⽣,课程)是个码,课程却决定了教材,这就叫做不完全依赖,或者说部分依赖。出现这样的情况,就不满⾜第⼆范式!
有什么不好吗?你可以想想:
1、校长要新增加⼀门课程叫“微积分”,教材是《⼤学数学》,怎么办?学⽣还没选课,⽽学⽣⼜是主属性,主属性不能空,课程怎么记录呢,教材记到哪呢? ……郁闷了吧?(插⼊异常)
2、下学期没学⽣学⼀年级语⽂(上)了,学⼀年级语⽂(下)去了,那么表中将不存在⼀年级语⽂(上),也就没了《⼩学语⽂1》。这时候,校长问:⼀年级语⽂(上)⽤的什么教材啊?……郁闷了吧?(删除异常)
3、校长说:⼀年级语⽂(上)换教材,换成《⼤学语⽂》。有10000个学⽣选了这么课,改动好⼤啊!改累死了……郁闷了吧?(修改异常)
那应该怎么解决呢?投影分解,将⼀个表分解成两个或若⼲个表
学⽣课程⽼师⽼师职称教室上课时间
⼩明⼀年级语⽂(上)⼤宝副教授10114:30
学⽣上课表新
课程教材
⼀年级语⽂(上)《⼩学语⽂1》
课程的表
第三范式(3NF):符合2NF,并且,消除传递依赖
上⾯的“学⽣上课表新”符合2NF,可以这样验证:两个主属性单独使⽤,不⽤确定其它四个⾮主属性的任何⼀个。但是它有传递依赖! 在哪呢?问题就出在“⽼师”和“⽼师职称”这⾥。⼀个⽼师⼀定能确定⼀个⽼师职称。有什么问题吗?想想:
1、⽼师升级了,变教授了,要改数据库,表中有N条,改了N次……(修改异常)
2、没⼈选这个⽼师的课了,⽼师的职称也没了记录……(删除异常)
3、新来⼀个⽼师,还没分配教什么课,他的职称记到哪?……(插⼊异常)
那应该怎么解决呢?和上⾯⼀样,投影分解:
学⽣课程⽼师教室上课时间
⼩明⼀年级语⽂(上)⼤宝10114:30
⽼师⽼师职称
⼤宝副教授
BC范式(BCNF):符合3NF,并且,主属性不依赖于主属性
若关系模式属于第⼀范式,且每个属性都不传递依赖于键码,则R属于BC范式。
通常BC范式的条件有多种等价的表述:每个⾮平凡依赖的左边必须包含键码;每个决定因素必须包含键码。BC范式既检查⾮主属性,⼜检查主属性。当只检查⾮主属性时,就成了第三范式。满⾜BC范式的关系都必然满⾜第三范式。还可以这么说:若⼀个关系达到了第三范式,并且它只有⼀个候选码,或者它的每个候选码都是单属性,则该关系⾃然达到BC范式。
⼀般,⼀个数据库设计符合3NF或BCNF就可以了。在BC范式以上还有第四范式、第五范式。
第四范式:要求把同⼀表内的多对多关系删除。
第五范式:从最终结构重新建⽴原始结构。
第⼀范式
第⼀范式:所有属性都是不可分割的原⼦值。
也就是每个属性都是不可再分的。
例如下图就不符合第⼀范式的要求
实际上,1NF是所有关系型数据库的最基本要求,你在关系型数据库管理系统(RDBMS),例如SQL Server,Oracle,MySQL中创建数据表的时候,如果数据表的设计不符合这个最基本的要求,那么操作⼀定是不能成功的。如果我们要在RDBMS中表现表中的数据,就得设计为下图的形式:
第⼆范式(2NF)
第⼆范式:在第⼀范式的基础上,要求⾮主属性都要和码有完全依赖关系
所谓完全依赖是指不能存在仅依赖码⼀部分的属性,必须是依赖全部属性。(区别于部分依赖)
如果有哪些数据只和码的⼀部份有关的话,它就不符合第⼆范式。同时可以得出:如果⼀个数据表的码只有单⼀⼀个字段的话,它就⼀定符合第⼆范式(前提是该数据表符合第⼀范式)。
(码可以由多个字段组成联合码,所以码可以是多属性)
2NF在1NF的基础之上,消除了⾮主属性对于码的部分属性依赖。
⾸先来看看下图
(1)每⼀名学⽣的学号、姓名、系名、系主任这些数据重复多次。每个系与对应的系主任的数据也重复多次——数据冗余过⼤
(2)假如学校新建了⼀个系,但是暂时还没有招收任何学⽣(⽐如3⽉份就新建了,但要等到8⽉份才招⽣),那么是⽆法将系名与系主任的数据单独地添加到数据表中去的 ——插⼊异常
(3)假如将某个系中所有学⽣相关的记录都删除,那么所有系与系主任的数据也就随之消失了(⼀个系所有学⽣都没有了,并不表⽰这个系就没有了)。——删除异常
(4)假如李⼩明转系到法律系,那么为了保证数据库中数据的⼀致性,需要修改三条记录中系与系主任的数据。——修改异常
所以这张表肯定不符合设计规范。我们来通过第⼆范式修改。
⾸先什么是依赖?
依赖
若在⼀张表中,在属性(或属性组)X的值确定的情况下,必定能确定属性Y的值,那么就可以说Y函数依赖于X,写作 X → Y。
例如,对于上图中的数据,不到任何⼀条记录,它们的学号相同⽽对应的姓名不同。所以我们可以说姓名函数依赖于学号,写作学号→姓名。但是反过来,因为可能出现同名的学⽣,所以有可能不同的两条学⽣记录,它们在姓名上的值相同,但对应的学号不同,所以我们不能说学号函数依赖于姓名。
然后什么是码?
码
设 K 为某表中的⼀个属性或属性组,若除 K 之外的所有属性都完全函数依赖于 K(这个“完全”不要漏了),那么我们称 K 为候选码,简称为码。在实际中我们通常可以理解为:假如当 K 确定的情况下,该表除 K 之外的所有属性的值也就随之确定,那么 K 就是码。⼀张表中可以有超过⼀个码。(实际应⽤中为了⽅便,通常选择其中的⼀个码作为主码)
如图中我们可以知道该表的码是(学号、课名)
对于第⼆范式,所有的⾮主属性要依赖于全部主属性。
由图中我们可以得到两个主属性:学号和课程
“学号“和”课程“就组成了联合主键。(⼀个表只有⼀个主键。主键可以由⼀个字段,也可以由多个字段组成)
因为我们可以通过学号来确定⼀个学⽣的姓名系名系主任这三个属性,⽆法确定课程和分数属性。
通过学⽣的学号和课程两个属性,可以确定分数。
对于(学号,课名)→姓名,有学号→姓名,存在⾮主属性姓名对码(学号,课名)的部分依赖。
对于(学号,课名)→系名,有学号→系名,存在⾮主属性系名对码(学号,课名)的部依赖。
对于(学号,课名)→系主任,有学号→系主任,存在⾮主属性系主任对码(学号,课名)的部分依赖。
所以表3存在⾮主属性对于码的部分函数依赖,最⾼只符合1NF的要求,不符合2NF的要求。
所以做出修改
删除某个系中所有的学⽣记录
该系的信息仍然全部丢失。——⽆改进
所以我们要使⽤第三范式。
第三范式(3NF)
第三范式:任何⾮主属性不依赖于其它⾮主属性。
3NF在2NF的基础之上,消除了⾮主属性对于码的传递函数依赖。
对于选课表,码为(学号,课名),主属性为学号和课名,⾮主属性只有⼀个,为分数,不可能存在传递函数依赖,所以选课表的设计,符合3NF的要求。
对于学⽣表,主码为学号,主属性为学号,⾮主属性为姓名、系名和系主任。因为学号→系名,同时系名→系主任,所以存在⾮主属性系主任对于码学号的传递函数依赖,所以学⽣表的设计,不符合3NF的要求。
为了让数据表设计达到3NF,我们必须进⼀步进⾏模式分解为以下形式:
选课(学号,课名,分数)
学⽣(学号,姓名,系名)
系(系名,系主任)
新的函数依赖关系如图
修改后的表
第⼆范式和第三范式就是为了消除⾮主属性对码的部分函数依赖和传递函数依赖
BC范式
BC范式在 3NF 的基础上消除主属性对于码的部分与传递函数依赖。
要了解 BCNF 范式,那么先看这样⼀个问题:
若:
某公司有若⼲个仓库;
每个仓库只能有⼀名管理员,⼀名管理员只能在⼀个仓库中⼯作;
⼀个仓库中可以存放多种物品,⼀种物品也可以存放在不同的仓库中。每种物品在每个仓库中都有对应的数量。
那么关系模式仓库(仓库名,管理员,物品名,数量)属于哪⼀级范式?
答:已知函数依赖集:仓库名→管理员,管理员→仓库名,(仓库名,物品名)→数量
码:(管理员,物品名),(仓库名,物品名)
主属性:仓库名、管理员、物品名
⾮主属性:数量
∵不存在⾮主属性对码的部分函数依赖和传递函数依赖。∴此关系模式属于3NF。
基于此关系模式的关系(具体的数据)可能如图所⽰:
好,既然此关系模式已经属于了 3NF,那么这个关系模式是否存在问题呢?我们来看以下⼏种操作:
先新增加⼀个仓库,但尚未存放任何物品,是否可以为该仓库指派管理员?——不可以,因为物品名也是主属性,根据实体完整性的要求,主属性不能为空。
某仓库被清空后,需要删除所有与这个仓库相关的物品存放记录,会带来什么问题?——仓库本⾝与管理员的信息也被随之删除了。
如果某仓库更换了管理员,会带来什么问题?——这个仓库有⼏条物品存放记录,就要修改多少次管理员信息。
从这⾥我们可以得出结论,在某些特殊情况下,即使关系模式符合 3NF 的要求,仍然存在着插⼊异常,修改异常与删除异常的问题,仍然不是 ”好“ 的设计。
造成此问题的原因:存在着主属性对于码的部分函数依赖与传递函数依赖。(在此例中就是存在主属性【仓库名】对于码【(管理员,物品名)】的部分函数依赖。
解决办法就是要在 3NF 的基础上消除主属性对于码的部分与传递函数依赖。
仓库(仓库名,管理员)
库存(仓库名,物品名,数量)
这样,之前的插⼊异常,修改异常与删除异常的问题就被解决了。
---------------------
作者:douunderstand
来源:CSDN
原⽂:blog.csdn/douunderstand/article/details/70159540
版权声明:本⽂为博主原创⽂章,转载请附上博⽂链接!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论