【转】关系型数据库的设计范式1NF2NF3NFBCNF
本⽂转载⾃:
⼀、缘由:
要做好DBA,就要更好地理解数据库设计范式。数据库范式总结概览:
为了更好地理解数据库的设计范式,这⾥借⽤⼀下知乎刘慰⽼师的解释,很通俗易懂。⾮常感谢!
⼆、具体说明:
⾸先要明⽩”范式(NF)”是什么意思。按照教材中的定义,范式是“符合某⼀种级别的关系模式的集合,表⽰⼀个关系内部各属性之间的联系的合理化程度”。
很晦涩吧?实际上你可以把它粗略地理解为⼀张数据表的表结构所符合的某种设计标准的级别。就像家⾥装修买建材,最环保的是E0级,其次是E1级,还有E2级等等。
数据库范式也分为1NF,2NF,3NF,BCNF,4NF,5NF。⼀般在我们设计关系型数据库的时候,最多考虑到BCNF就够。符合⾼⼀级范式的设计,必定符合低⼀级范式,例
如符合2NF的关系模式,必定符合1NF。
接下来就对每⼀级范式进⾏⼀下解释,⾸先是第⼀范式(1NF):
慕课网的课件能下载吗i 符合1NF的关系(你可以理解为数据表。“关系”和“关系模式”的区别,类似于⾯向对象程序设计中”类“与”对象“的区别。”关系“是”关系模式“的⼀个实例,
你可以把”关系”理解为⼀张带数据的表,⽽“关系模式”是这张数据表的表结构。1NF的定义为:符合1NF的关系中的每个属性都不可再分。表1所⽰的情况,就不符合1NF的要求。
【表1】
实际上,1NF是所有关系型数据库的最基本要求,你在关系型数据库管理系统(RDBMS),例如SQL Server,Oracle,MySQL中创建数据表的时候,如果数据表的设计
不符合这个最基本的要求,那么操作⼀定是不能成功的。也就是说,只要在RDBMS中已经存在的数据表,⼀定是符合1NF的。如果我们要在RDBMS中表现表中的数据,就得
设计为表2的形式:
【表2】
但是仅仅符合1NF的设计,仍然会存在数据冗余过⼤,插⼊异常,删除异常,修改异常的问题,例如对于表3中的设计:
【表3】
1.每⼀名学⽣的学号、姓名、系名、系主任这些数据重复多次。每个系与对应的系主任的数据也重复多次——数据冗余过⼤
2.假如学校新建了⼀个系,但是暂时还没有招收任何学⽣(⽐如3⽉份就新建了,但要等到8⽉份才招⽣),那么是⽆法将系名与系主任的数据单独地添加到数据表中去的 (注1)——插⼊异常
注1:根据三种关系完整性约束中实体完整性的要求,关系中的码(注2)所包含的任意⼀个属性都不能为空,所有属性的组合也不能重复。为了满⾜此要求,图中的表,
只能将学号与课名的组合作为码,否则就⽆法唯⼀地区分每⼀条记录。
注2:码:关系中的某个属性或者某⼏个属性的组合,⽤于区分每个元组(可以把“元组”理解为⼀张表中的每条记录,也就是每⼀⾏)。
3.假如将某个系中所有学⽣相关的记录都删除,那么所有系与系主任的数据也就随之消失了(⼀个系所有学⽣都没有了,并不表⽰这个系就没有了)。——删除异常
4.假如李⼩明转系到法律系,那么为了保证数据库中数据的⼀致性,需要修改三条记录中系与系主任的数据。——修改异常
正因为仅符合1NF的数据库设计存在着这样那样的问题,我们需要提⾼设计标准,去掉导致上述四种问题的因素,使其符合更⾼⼀级的范式(2NF),这就是所谓的“规范化”。
第⼆范式(2NF)在关系理论中的严格定义我这⾥就不多介绍了(因为涉及到的铺垫⽐较多),只需要了解2NF对1NF进⾏了哪些改进即可。其改进是,2NF在1NF的基础之上,
消除了⾮主属性对于码的部分函数依赖。接下来对这句话中涉及到的四个概念——“函数依赖”、“码”、“⾮主属性”、与“部分函数依赖”进⾏⼀下解释。
函数依赖
我们可以这么理解(但并不是特别严格的定义):若在⼀张表中,在属性(或属性组)X的值确定的情况下,必定能确定属性Y的值,那么就可以说Y函数依赖于X,写作 X → Y。
也就是说,在数据表中,不存在任意两条记录,它们在X属性(或属性组)上的值相同,⽽在Y属性上的值不同。这也就是“函数依赖”名字的由来,类似于函数关系 y = f(x),
mysql面试题 知乎在x的值确定的情况下,y的值⼀定是确定的。
例如,对于表3中的数据,不到任何⼀条记录,它们的学号相同⽽对应的姓名不同。所以我们可以说姓名函数依赖于学号,写作 学号 →姓名。但是反过来,因为可能出现同名的学⽣,
所以有可能不同的两条学⽣记录,它们在姓名上的值相同,但对应的学号不同,所以我们不能说学号函数依赖于姓名。表中其他的函数依赖关系还有如:web代码大全表解释
系名 → 系主任
学号 → 系主任
(学号,课名) → 分数
但以下函数依赖关系则不成⽴:
学号 → 课名
学号 → 分数
课名 → 系主任
(学号,课名) → 姓名
从“函数依赖”这个概念展开,还会有三个概念:
完全函数依赖
在⼀张表中,若 X → Y,且对于 X 的任何⼀个真⼦集(假如属性组 X 包含超过⼀个属性的话),X ' → Y 不成⽴,那么我们称 Y 对于
X 完全函数依赖,记作 X F→ Y。(
那个F应该写在箭头的正上⽅,没办法打出来……,正确的写法如图1)
图1
例如:
学号 F→ 姓名
(学号,课名) F→ 分数 (注:因为同⼀个的学号对应的分数不确定,同⼀个课名对应的分数也不确定)
部分函数依赖
假如 Y 函数依赖于 X,但同时 Y 并不完全函数依赖于 X,那么我们就称 Y 部分函数依赖于 X,记作 X P→ Y,如图2。
图2
例如:
(学号,课名) P→ 姓名
传递函数依赖
假如 Z 函数依赖于 Y,且 Y 函数依赖于 X (严格来说还有⼀个X 不包含于Y,且 Y 不函数依赖于Z的前提条件),那么我们就称 Z 传递函数依赖于 X ,记作 X T→ Z,如图3。
图3
码
设 K 为某表中的⼀个属性或属性组,若除 K 之外的所有属性都完全函数依赖于 K(这个“完全”不要漏了),那么我们称 K 为候选码,简称为码。在实际中我们通常可以理解为:
假如当 K 确定的情况下,该表除 K 之外的所有属性的值也就随之确定,那么 K 就是码。⼀张表中可以有超过⼀个码。(实际应⽤中为了⽅便,通常选择其中的⼀个码作为主码)
例如:
对于表3,(学号、课名)这个属性组就是码。该表中有且仅有这⼀个码。(假设所有课没有重名的情况)
⾮主属性
包含在任何⼀个码中的属性成为主属性。
例如:
对于表3,主属性就有两个,学号 与 课名。
终于可以回过来看2NF了。⾸先,我们需要判断,表3是否符合2NF的要求?根据2NF的定义,判断的依据实际上就是看数据表中是否存在⾮主属性对于码的部分函数依赖。
若存在,则数据表最⾼只符合1NF的要求,若不存在,则符合2NF的要求。判断的⽅法是:
第⼀步:出数据表中所有的码。
第⼆步:根据第⼀步所得到的码,出所有的主属性。菜鸟教程有用吗
第三步:数据表中,除去所有的主属性,剩下的就都是⾮主属性了。
第四步:查看是否存在⾮主属性对码的部分函数依赖。
对于表3,根据前⾯所说的四步,我们可以这么做:在sql语言中授权命令是
第⼀步:
1. 查看所有每⼀单个属性,当它的值确定了,是否剩下的所有属性值都能确定。
2. 查看所有包含有两个属性的属性组,当它的值确定了,是否剩下的所有属性值都能确定。
3. ……
4. 查看所有包含了六个属性,也就是所有属性的属性组,当它的值确定了,是否剩下的所有属性值都能确定。
看起来很⿇烦是吧,但是这⾥有⼀个诀窍,就是假如A是码,那么所有包含了A的属性组,如(A,B)、(A,C)、(A,B,C)等等,都不是码了(因为作为码的要求⾥有⼀个“完全函数依赖”)。
图4表⽰了表中所有的函数依赖关系:
图4
这⼀步完成以后,可以得到,表3的码只有⼀个,就是(学号、课名)。
第⼆步:
主属性有两个:学号 与 课名
第三步:
⾮主属性有四个:姓名、系名、系主任、分数
第四步:
对于(学号,课名) → 姓名,有 学号 → 姓名,存在⾮主属性 姓名 对码(学号,课名)的部分函数依赖。
对于(学号,课名) → 系名,有 学号 → 系名,存在⾮主属性 系名 对码(学号,课名)的部分函数依赖。
对于(学号,课名) → 系主任,有 学号 → 系主任,存在⾮主属性 对码(学号,课名)的部分函数依赖。
所以表3存在⾮主属性对于码的部分函数依赖,最⾼只符合1NF的要求,不符合2NF的要求。
为了让表3符合2NF的要求,我们必须消除这些部分函数依赖,只有⼀个办法,就是将⼤数据表拆分成两个或者更多个更⼩的数据表,在拆分的过程中,要达到更⾼⼀级范式的
要求,这个过程叫做”模式分解“。模式分解的⽅法不是唯⼀的,以下是其中⼀种⽅法:
选课(学号,课名,分数)
学⽣(学号,姓名,系名,系主任)
windows句柄我们先来判断以下,选课表与学⽣表,是否符合了2NF的要求?
对于选课表,其码是(学号,课名),主属性是学号和课名,⾮主属性是分数,学号确定,并不能唯⼀确定分数,课名确定,也不能唯⼀确定分数,所以不存在⾮主属性分数
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论