数据库之数据库范式
1.基础概念 实体 :现实世界中客观存在并可以被区别的事物。比如“一个学生”、“一本书”、“一门课”等等。得强调的是这里所说的“事物”不仅仅是看得见摸得着的“东西”,它也可以是虚拟的,不如说“老师与学校的关系”。 属性 :教科书上解释为:“实体
1.基础概念
实体:现实世界中客观存在并可以被区别的事物。比如“一个学生”、“一本书”、“一门课”等等。值得强调的是这里所说的“事物”不仅仅是看得见摸得着的“东西”,它也可以是虚拟的,不如说“老师与学校的关系”。
属性:教科书上解释为:“实体所具有的某一特性”,由此可见,属性一开始是个逻辑概念,比如说,“性别”是“人”的一个属性。在关系数据库中,属性又是个物理概念,属性可以看作是“表的一列”。
元组:表中的一行就是一个元组。
分量:元组的某个属性值。在一个关系数据库中,它是一个操作原子,即关系数据库在做任何操作的时候,属性是“不可分的”。否则就不是关系数据库了。
码:表中可以唯一确定一个元组的某个属性(或者属性组),如果这样的码有不止一个,那么都叫候选码,我们从候选码中挑一个出来做老大,它就叫主码。
全码:如果一个码包含了所有的属性,这个码就是全码。
候选码:若关系中的某一属性或属性组的值能唯一的标识一个元组,而其任何真子集都不能再标识,则称该属性组为(超级码)候选码。
主码:主码(主键,primary key)是被挑选出来,作表的行的唯一标识的候选关码。一个表只有一个主码。
外码:一个属性(或属性组),它不是码,但是它别的表的码,它就是外码。
主属性:一个属性只要在任何一个候选码中出现过,这个属性就是主属性。
非主属性:与上面相反,没有在任何候选码中出现过,这个属性就是非主属性。
函数依赖:设R(U)是一个属性集U上的关系模式,X和Y是U的子集。若对于R(U)的任意两个可能的关系r1、r2,若r1[x]=r2[x],则r1[y]=r2[y],或者若r1[x]不等于r2[x],则r1[y]不等于r2[y],称X决定Y,或者Y依赖X。通俗来说,设X,Y是关系R的两个属性集合,当任何时刻R中的任意两个元组中的X属性值相同时,则它们的Y属性值也相同,则称X函数决定Y,或Y函数依赖于X。
完全函数依赖:设X,Y是关系R的两个属性集合,X’是X的真子集,存在X→Y,但对每一个X'都有X'!→Y,则称Y完全函数依赖于X。
部分函数依赖:设X,Y是关系R的两个属性集合,存在X→Y,若X’是X的真子集,存在X’→Y,则称Y部分函数依赖于X。
传递依赖:在关系模式R(U)中,设X,Y,Z是U的不同的属性集合,如果X→Y成立,且(Y不属于X,Y→X不成立),Y→Z成立,XYΠZ=?,则称Z传递函数依赖(transitive functional dependency) 于X。式中XY表示是。定义中说明,是因为如果Y→X,则有X?Y,实际形成X→Z是直接函数依赖,而非传递函数依赖。例如,在STUDENT关系模式中,假定班级编号都与系的名称相关。例如:计算机系2000年入学的学生班级有6个,其班级名称为:JS001,JS002,JS003,JS004,JS005,JS006。这样,可以由学生的学号确定学生所在的班级,由班级名称就可以确定学生所在系,形成传递函数依赖:
SNO→SCLASS→SDEP
2.范式介绍
1)第一范式(1NF)
所谓第一范式(1NF)是指在关系模型中,对域添加的一个规范要求,所有的域都应该是原子性的,即数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。即实体中的某个属性有多个值时,必须拆分为不同的属性。在符合第一范式(1NF)表中的每个域值只能是实体的一个属性或一个属性的一部分。简而言之,第一范式就是无重复的域。
2)第二范式(2NF)属性
在1NF的基础上,非码属性必须完全依赖于主键[在1NF基础上消除非主属性对主码的部分函数依赖]。第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。简而言之,第二范式就是在第一范式的基础上属性完全依赖于主键。
3)第三范式(3NF)属性
在1NF基础上,任何非主属性不依赖于其它非主属性[在2NF基础上消除传递依赖]。第三范式(3NF)是第二范式(2NF)的一个子集,即满足第三范式(3NF)必须满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个关系中不包含已在其它关系已包含的非主关键字信息。例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在的员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。简而言之,第三范式就是属性不依赖于其它非主属性,也就是在满足2NF的基础上,任何非主属性不得传递依赖于主属性。
4)巴德斯科范式(BCNF)属性
如果关系模式R(U,F)的所有属性(包括主属性和非主属性)都不传递依赖于R的任何候选关键字,那么称关系R是属于BCNF的。或是关系模式R中,每个决定因素都包含关键字(而不是被关键字所包含)。巴德斯科范式(BCNF)是第三范式(3NF)的一个子集,即满足巴德斯科范式(BCNF)必须满足第三范式(3NF)。通常情况下,只是对第二范式与第三范式中设计规范要求更强,因而被认为是修正第三范式,它事实上是对第三范式的修正,使数据库冗余度更小。
3.实例分析
下面以一个学校的学生系统为例分析说明,这几个范式的应用。
1)第一范式实例分析:
首先第一范式(1NF):数据库表中的字段都是单一属性的,不可再分。单一属性由基本类型构成,包括整型、实数、字符型、逻辑型、日期型等。确定一下要设计的内容包括:学号、学生姓名、年龄、性别、课程、课程学分、系别、学科成绩,系办地址、系办电话等信息。我们对于这些信息,说关心的问题有如下几个方面。
- 学生有那些基本信息
- 学生选了那些课,成绩是什么
- 每个课的学分是多少
- 学生属于那个系,系的基本信息是什么。
2)第二范式实例分析:
首先把所有这些信息放到一个表中(学号,学生姓名、年龄、性别、课程、课程学分、系别、学科成绩,系办地址、系办电话)下面存在如下的依赖关系。
(学号, 课程名称) → (姓名, 年龄, 成绩, 学分)
问题分析:
(学号,课程名称)作为主码,但姓名、年龄完全依赖于学号,学分完全依赖于课程名称,所以不满足第二范式。可能导致以下的问题:
数据冗余:同一门课程由n个学生选修,"学分"就重复n-1次;同一个学生选修了m门课程,姓名和年龄就重复了m-1次。
更新异常:
1)若调整了某门课程的学分,数据表中所有行的"学分"值都要更新,否则会出现同一门课程学分不同的情况。
2)假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有"学号"关键字,课程名称和学分也无法记录入数据库。
删除异常 :假设一批学生已经完成课程的选修,这些选修记录就应该从数据库表中删除。但是,与此同时,课程名称和学分信息也被删除了。很显然,这也会导致插入异常
解决方案
把选课关系表SelectCourse改为如下三个表:
学生:Student(学号,姓名,年龄,性别,系别,系办地址、系办电话);
课程:Course(课程名称,学分);
选课关系:SelectCourse(学号,课程名称,成绩)。
3)第三范式实例分析
接着看上面的学生表Student(学号,姓名,年龄,性别,系别,系办地址、系办电话),关键字为单一关键字"学号",因为存在如下依赖关系:
(学号)→ (姓名,年龄,性别,系别,系办地址、系办电话)
问题分析:
但是还存在下面的决定关系
(学号) → (所在系办)→(系办地点,系办电话)
即存在非关键字段"系办地点"、"系办电话"对关键字段"学号"的传递函数依赖。
它也会存在数据冗余、更新异常、插入异常和删除异常的情况。
解决方案:
根据第三范式把学生关系表分为如下两个表就可以满足第三范式了。
学生:(学号,姓名,年龄,性别,系别);
系别:(系别,系办地址、系办电话)。
4)第四范式(BNCF范式)实例分析:
例:配件管理关系模式 wpe(wid,pid,eid,qnt)分别表仓库号,配件号,职工号,数量。有以下条件:、
a.一个仓库有多个职工。
b.一个职工仅在一个仓库工作。
c.每个仓库里一种型号的配件由专人负责,但一个人可以管理几种配件。
d.同一种型号的配件可以分放在几个仓库中。
问题分析:
1. pid不能确定qnt,由组合属性(wid,pid)来决定,存在函数依赖(wid,pid)-> qnt。
2. 每个仓库里的一种配件由专人负责,而一个人可以管理几种配件,所以有(wid,pid)-> eid。
3. 一个职工仅在一个仓库工作,有eid -> wid。
4. 每个仓库里的一种配件由专人负责,而一个职工仅在一个仓库工作,有(eid,pid)-> qnt。
找一下候选关键字。因为(wid,pid)-> qnt,(wid,pid)-> eid,因此(wid,pid)可以决定整个元组,是一个候选关键字。根据eid -> wid,(eid,pid)-> qnt,故(eid,pid)也能决定整个元组,为另一个候选关键字。属性eid,eid,pid
均为主属性;只有一个非主属性qnt,它对任何一个候选关键字都是完全函数依赖的,并且是直接依赖,所以该关系模式是3NF。
分析一下主属性。因为eid -> wid,主属性eid是wid的决定因素,但是它本身不是关键字,只是组合关键字的一部分。这就造成主属性wid对另外一个候选关键字(eid,pid)的部分依赖,因为(eid,pid)-> eid但反过来不成立,而pid -> wid,故(eid,pid)->eid, eid-> wid 也是传递依赖。
虽然没有非主属性对候选关键字的传递依赖,但存在主属性对候选关键字的传递依赖,同样也会带来麻烦。如一个新职工分配到仓库工作,但暂时处于实习阶段,没有独立负责对某些配件的管理任务。由于缺少关键字的一部分pid而无法插入到该关系中去。又如某个人改成不管配件了去负责安全,则在删除配件的同时该职工也会被删除。
解决办法:分成管理ep(eid,pid,qnt),关键字是(eid,pid)和工作ew(eid,wid)其关键字是eid。
缺点:分解后函数依赖的保持性较差。如此例中,由于分解,函数依赖(wid,pid)-> eid 丢失了,因而对原来的语义有所破坏。没有体现出每个仓库里一种部件由专人负责。有可能出现一部件由两个人或两个以上的人来同时管理。因此,分解之后的关系模式降低了部分完整性约束。