数据库六大范式简述

304 阅读11分钟

数据库范式

数据库范式指的是对于数据库中关系数据库规范化理论。这篇内容参考《数据库系统概论》整理。一个关系模式应该是一个五元组R(U,D,DOM,F),对于这里我们只需要关注R<U,F>即可。其中R标识关系名称,U标识一组属性(数据库表中的字段),F标识U上的一组数据依赖(姓名依赖学号)。

tips:可以把元组理解成一种模式的集合,描述为对于关系R他有U(一组属性),D(属性组U中的属性所来自的域),DOM(属性到域的映射),F(属性组U上的一组数据依赖)组成。类似python中tuple的概念,对于一个方法R返回U,D,DOM,F这么一个元组

一些概念

这些概念类似于一种定义,在后面的文章中我们不会在阐述这些定义的含义,因此后续的内容可以参考这里看。

域;domain

一组具有相同数据类型的值的集合

例如:自然数、整数、实数组成的集合,都可以是域

笛卡尔积;cartesian product

是域上的一种集合运算

例如:A:{a,b};B:{c,d};他们的笛卡尔积是{ac,ad,bc,bd}

域的基数;cardinal number

一个域允许不同取值个数称为域的基数.例如:A:{a,b,c}他的基数是3

关系;relation

D1xD2x...xDn的子集叫做在域D1,D2,...,Dn上的关系,标识为R(D1,D2,...,D3)。R表示关系的名字,n标识关系的目或者度(degree)

属性

关系是笛卡尔积的有限子集,所以关系是一张二维表,表的每一行对应一个元组,表的每一列对应一个域。每个列都有一个名字,称为属性(attribute)。n目关系必有n个属性。

候选码;candidate key

若关系中某一属性组的值能唯一标识一个元组,而子集不能,则该属性组维候选码。或者设K为R<U,F>中的属性或属性组合,如果U完全依赖于K,则K为R的候选码

例如对于学生表中,学号是一个候选码,班级+姓名(同班不重名)也是一个候选码……。所以我个人理解其实候选码可以是一个二级索引(实际MySQL中二级索引也不一定是候选码)+唯一索引

超码;Surpkey

若设K为R<U,F>中属性或属性组合,如果U部分依赖于K,则K为R的超码。因此候选码是最小的超码(超码包括了候选码)

例如对于学生表,学号是一个超码,同理学号,姓名可以是一个超码。但是(学号,姓名)不是一个候选码

主码;primary key

若一个关系有多个首选码,则选定其中一个为主码

例如对于学生表,可以选择学号为主码,也可以选择班级+姓名作为主码。

主属性;prime attribute;非主属性

候选码中的每个属性,都可以成为主属性,在关系中不包含在任何候选码中的属性称为非主属性或非码属性

全码;all-key

关系模式中所有属性是这个关系模式的候选码,称为全码

M:M的中间表就可以是全码

函数依赖;FunctionalDependency;FD

设R(U)是属性集U上的关系模式,X,Y是U的子集。对于R(U)的任意一个可能关系r,r中不可能存在两个元组在X上的属性值相等,但在Y上的属性值不相等。则称X函数确定Y或Y函数依赖于X,记作X→Y

简单说就是Y=f(X),例如学生表中姓名函数依赖于学号(学号→姓名)。注意函数依赖是一种语义范畴的概念,理论上在足够限定条件下任何事物间都是函数依赖的,例如当姓名是唯一时,学号也可以函数依赖于姓名。

非平凡函数依赖

X→Y,但X不包含Y,则称X→Y为非平凡的函数依赖。即一个关系决定另一个关系。

例如对于学生表,学号→姓名,这是一个非平凡函数依赖。因为姓名不是学号的子集,他们是没有交集的

平凡函数依赖

X→Y,且Y是X的子集

例如对于学生表,学号,姓名→学号,这是一个平凡函数依赖。因为Y是X的子集。对于任一关系模式,平凡函数依赖都是成立的。

决定因素;determinant

若X→Y,则X称为这个函数依赖的决定属性组,即决定因素

完全函数依赖

对于R(U),如果X→Y,并且对于X的任何一个真子集X‘,都有Y不依赖与X’,则Y对X完全函数依赖

例如学生表中,规定学生+院系是唯一的,则学生,院系->学号。因此完全函数依赖一定是非平凡的函数依赖

部分函数依赖

在R(U)中,如果X->Y,但是Y并不是完全依赖于X,则称Y对X的部分函数依赖

例如学生表中,学号,姓名->性别。这其中对于学号->性别也是函数依赖,因此对于前者就是部分函数依赖

传递函数依赖

在R(U)中,如果X->Y(且不平凡)且Y不依赖于X时。存在Y->Z(不平凡)则称Z对X传递函数依赖

例如,学号->科目,科目->成绩,那么成绩对学号传递函数依赖,传递函数依赖不一定是函数依赖,显然相同的成绩可能有不同的学号

注意这里加了条件Y不依赖与X,因为如果Y依赖于X时,X和Z就是直接函数依赖的关系了。

多值依赖;Multi-Valued Dependency;MVD

设R(U)是属性及U上的一个关系模式。X,Y,Z是U的子集,并且Z=U-X-Y。关系模式R(U)中多值依赖X->->Y成立,当且仅当R(U)的任意关系r,给定的一对(x,z)值,有一组Y的值,这组值仅仅决定于x值而与z值无关。

多值依赖具有对称性:X->->Y,X->->Z,其中Z=U-X-Y

多值依赖具有传递性:X->->Y,Y->->Z,则X->->Z-Y

例如,对于R(老师,科目,学生姓名)且一门课就一个老师,一个老师可以上多门课,学生姓名不重名。此时对于科目和学生姓名的对应关系其实和老师没有关系,因此老师->->科目

平凡多值依赖

对于Z=U-X-Y,若X->->Y,而Z为空集,则X->->Y为平凡多值依赖。

简单说就是R(学生,成绩),那么学生->->成绩,这是一个平凡多值依赖

连接依赖

如果将关系 R的所有属性在R的实例I上分别进行投影操作,然后将这些投影的结果进行连接运算后其结果仍等于I,则称该实例I 满足连接依赖。

例如R(A,B,C)满足R1(A,B),R2(B,C),R3(A,C),并且他们三个链接起来依旧是R,此时就满足连接依赖了

范式

关系数据库中关系是要满足一定要求的,满足不同程度要求成为不同的范式。范式共有1NF-5NF共6中(其中BC范式是3范式的补充)

image-20220929133419141

各个范式之间的关系可以参考这张图。一个低级范式的关系模式通过模式分解可以转换为若干个高一级的范式的关系模式集合,这个过程叫做规范化

第一范式 1NF

在一张二维表中每一个属性都必须是一个不可分的数据项。满足这个条件的关系模式就是第一范式(1NF)

简单说只要是一张二维的数据表,而且每个表中的字段语义上不可以在拆分了就满足第一范式了。目前大多数场景都是满足第一范式,当然有一些场景可能不满足,例如一个列表字段我们用逗号分隔存储。

第二范式 2NF

在第一范式的基础上,每个非主属性完全函数依赖与任何一个候选码,则称为第二范式。

简单说就是任何一个候选码,必须对应唯一一个非主属性。例如学生学号作为候选码,姓名作为非主属性这是满足第二范式的。但是学生学号作为候选码,学生成绩作为非主属性,这只满足第一范式(而且连函数依赖都不满足)。

第三范式 3NF

在第二范式的基础上,每个非主属性即不传递依赖于码,也不部分依赖于码,则称为第三范式。

即每一个非主属性都完全依赖于码而不是,而不是存在传递依赖。例如学号作为码,学号->老师姓名(假定唯一),老师姓名->老师年龄。这种情况就是满足了第二范式但是不满足第三范式了。

解决上述情况只需要吧部分依赖拆成两张表即可

BC范式 BCNF

这是对3NF的扩充和修正。第三范式考虑的是,非主属性间存在传递依赖的关系,但是没有考虑到主属性和码存在传递依赖的关系。BC范式把他修正成了属性间不允许出现传递依赖。

关系模式R<U,F>中,若每一个决定个因素都包含码,则他属于BC范式。一个满足BCNF关系模式的有:

  • 所有非主属性对每一个码都是完全函数依赖。
  • 所有主属性对每一个不包含他的码也是完全函数依赖。
  • 没有任何属性完全函数依赖于非码的任何一组属性。

例如:对于R(学科号,老师姓名,学生姓名,成绩),老师、学生姓名是唯一的;一个老师只能交一科目,一个科目只有一个老师;同一个科目学生只能参加一次。函数依赖为:成绩->(学科号,学生姓名);成绩->(老师姓名,学生姓名);老师姓名->学科号;候选码是(学科号,学生姓名),(老师姓名,学生姓名)。由于单独学科号并不是这个表的候选码,因此这只是3NF。

其实BC范式存在的场景就是候选码和主属性存在传递依赖时,就代表候选码交叉后可能出现依赖的情况,这是对3NF的修正。

第四范式4NF

关系模式R<U,F>属于第一范式,如果对于R的每个非平凡多值依赖X->->Y(Y不包含与X),X都含有码,则该关系为第四范式

4NF就是限制关系模式的属性之间不允许有非平凡且非函数依赖的多值依赖

例如:对于R(学科号,老师姓名,学生姓名,成绩),老师、学生姓名是唯一的;老师和科目1:N;一个学生只能报一个老师的一个科目;他的候选码是(学科号,老师姓名,学生姓名)。函数依赖:(学科号,老师姓名,学生姓名)->成绩。所以他满足了BC范式,但是由于(学科号,老师姓名)和学生姓名无关,因此不满足第四范式。如果需要解决的话就吧R拆成R1(学科号,老师姓名),R2(老师姓名,学生姓名,成绩)

第五范式5NF

这一块书上并没有很明确的将他的含义,在网上找到了一些相关资料。第五范式(5NF)也称为投影联合范式(PJ / NF) 。 它旨在通过以多种格式分隔语义连接的关系来存储多值事实,以最大程度地减少关系数据库中的冗余。

简单说就是尽可能拆分R的关系模式,通过连接依赖的方式拆分,最终拆出来的结果不可以是5NF的时候,他就满足5NF了。