本文主要是介绍第一范式、第二范式、第三范式的区别(关系数据理论),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
关系数据理论
使用关系数据库理论来进行关系数据库的逻辑设计,简单来说就是针对一个具体问题,使用关系数据理论来构造适合于它的数据库模式。
⭐️数据依赖
数据依赖是一个关系内部属性与属性之间的一种约束关系。通过属性间值的相等与否体现出来的。是现实世界属性间相互联系的抽象,是数据内在的性质,是语义的体现。
数据依赖最重要的是函数依赖(Functional Dependency,FD)和多值依赖(Multi- Valued Dependency,MVD)。
函数依赖
函数依赖普遍存在于现实生活中,例如描述一个学生的关系,有学号(Sno)、姓名(Sname)、系名(Sdept)等属性。现实世界中,一个学生对应一个学生,一个学生只属于一个系,因而学号确定后,学生所在的系也就确定了,这就称为一个函数依赖。记作 S n o → S d e p t Sno \rightarrow Sdept Sno→Sdept(读作Sno决定Sdept)。
💡简单理解为Sno和Sdept之间存在某种函数对应关系。
函数依赖不是指关系模式R的某些关系满足的约束条件,而是指R的一切关系均要满足的约束条件的集合。
函数依赖相关术语
-
若 X → Y X \rightarrow Y X→Y,则称 X X X为这个函数依赖的决定属性组,又称决定因素,读作 X X X决定 Y Y Y。
⚠️X、Y是属性或者属性集, X → Y X \rightarrow Y X→Y是 Y Y Y依赖 X X X, X X X决定 Y Y Y。 -
X → Y X \rightarrow Y X→Y,但 Y ⊈ X Y \nsubseteq X Y⊈X,则称 X → Y X \rightarrow Y X→Y是非平凡的函数依赖。
⚠️ X ⊆ Y X \subseteq Y X⊆Y是 Y Y Y包含 X X X。 -
X → Y X \rightarrow Y X→Y,但 Y ⊆ X Y \subseteq X Y⊆X,则称 X → Y X \rightarrow Y X→Y是平凡的函数依赖。对于任一关系模式,平凡的函数依赖均必然成立,不反映新的语义(没什么用,一般不考虑)。
-
⭐️在 R ( U ) R(U) R(U)中,如果 X → Y X \rightarrow Y X→Y,并且对于 X X X的任何一个真子集 X ′ X^{'} X′,都有 X ′ ↛ Y X^{'} \nrightarrow Y X′↛Y,则称 Y Y Y对 X X X完全函数依赖,记作 X ⟶ F Y X\stackrel{F}{\longrightarrow}Y X⟶FY。
💡只有 X X X整个集合才能决定 Y Y Y成为完全函数依赖,存在 X X X中的一子属性决定 Y Y Y称为部分函数依赖。- ⭐️同理,若 X → Y X \rightarrow Y X→Y,但 Y Y Y不完全依赖于 X X X,则称** Y Y Y对 X X X部分函数依赖**,记作 X ⟶ P Y X\stackrel{P}{\longrightarrow}Y X⟶PY。
-
在 R ( U ) R(U) R(U)中,如果 X → Y X \rightarrow Y X→Y, Y → Z Y \rightarrow Z Y→Z( Y ↛ X , Y ⊈ X , Z ⊈ Y Y \nrightarrow X, Y \nsubseteq X,Z \nsubseteq Y Y↛X,Y⊈X,Z⊈Y),则称Z对X传递函数依赖,记作 X ⟶ 传 递 Y X\stackrel{传递}{\longrightarrow}Y X⟶传递Y。
这个地方的概念必须得看懂。
码的函数依赖定义
- 设 K K K为 R < U , F > R<U,F> R<U,F>中的属性火属性组合,若 K ⟶ F U K \stackrel{F}{\longrightarrow} U K⟶FU,即 U U U完全函数依赖于 K K K,则称 K K K为 R R R的候选码。若候选码多于一个,选定其中一个为主码。
- 如果 U U U部分函数依赖于 K K K,则称 K K K为超码。候选码是最小的超码,即 K K K的任一真子集都不是候选码。
- 包含在候选码中的属性成为主属性,否则称为非主属性。整个属性组全是码,称为全码。
🈚️多值依赖
范式与规范化
规范化要讨论一个模式的数据依赖会有哪些不好的性质,以及如何改造一个不好的模式。一个低一级范式的关系模式通过模式分解可以转换为若干个高一级范式的关系模式的集合,这种过程就叫规范化。
范式表示关系的某一级别,常称某一关系模式 R R R为第几范式, R R R为第几范式可以写成 R ∈ x N F R \in xNF R∈xNF,各种范式之间的关系为 5 N F ∈ 4 N F ∈ B C N F ∈ 3 N F ∈ 2 N F ∈ 1 N F 5NF \in 4NF \in BCNF\in 3NF \in 2NF \in 1NF 5NF∈4NF∈BCNF∈3NF∈2NF∈1NF 。
第一范式
关系作为一个二维表,要符合一个最基本的条件:每一个分量必须是不可分的数据项(表不能有子表)。满足了这个条件的关系模式就属于第一范式(1NF)。
第二范式
若 R ∈ 1 N F R∈1NF R∈1NF,且每一个非主属性完全函数依赖于任何一个候选码,则称为第二范式,记作 R ∈ 2 N F R∈2NF R∈2NF。
2NF通过消除部分函数依赖,可以在一定程度上减轻1NF中存在的插入异常、删除异常、数据冗余大、修改复杂等问题,但并不能完全消除关系模式的各种异常情况和数据冗余。
第三范式(3NF)
我们抛开形式化的定义,直接从一个例子入手来理解。
2NF回顾
例如,2NF采用投影分解法,把 S − L − C S-L-C S−L−C分解为两个关系模式: S C SC SC和 S − L S-L S−L,消除了 S − L − C S-L-C S−L−C中非主属性对码的部分函数依赖。
💡简单来说就是再拆分几张表出来,让表中只剩下完全依赖,部分依赖是一切问题的根源。
按照这种方法把1NF关系模式分解为多个2NF的关系模式,可以减轻1NF关系模式中存在的插入异常、删除异 常、数据冗余度大、修改复杂等问题,但并不能完全消除关系模式中的各种异常情况和数据冗余。
2NF中的问题
例如,在 S − L ( S n o , S d e p t , S l o c ) S-L(Sno, Sdept, Sloc) S−L(Sno,Sdept,Sloc)关系模型中, S l o c Sloc Sloc依赖于 S d e p t Sdept Sdept, S d e p t Sdept Sdept又依赖于 S n o Sno Sno,即 S − L S-L S−L中存在非主属性对码的传递函数依赖 S n o ⟶ 传 递 S l o c Sno\stackrel{传递}{\longrightarrow}Sloc Sno⟶传递Sloc。
然而,这其中存在的问题有:
-
插入异常
如果某个系暂时没有在校学生,我们就无法把这个系的信息存入数据库。 -
删除异常
如果某个系的学生全部毕业了,我们在删除该系全部学生信息的同时,就把这个系的信息也丢掉了。 -
数据冗余度大
每一个系的学生都住在同一个地方,按理来说只存一次就行了,但关于在每个学生信息里,该系的住处的信息却重复出现。 -
修改复杂
学校调整学生住处时,由于刚刚提到的关于每个系的住处信息是重复存储的,修改时必须同时更新该系所有学生的 S l o c Sloc Sloc属性值。
问题原因
S − L S-L S−L中 S l o c Sloc Sloc传递函数依赖于 S n o Sno Sno, 即非主属性传递函数依赖码。
💡可见非主依赖这个东西是一切问题的根源。
2NF问题的解决办法
依然是采用投影分解法,把 S − L S-L S−L分解为两个 关系模式,以消除传递函数依赖: S − D ( S n o , S d e p t ) S-D(Sno, Sdept) S−D(Sno,Sdept) , D − L ( S d e p t , S l o c ) D-L(Sdept, Sloc) D−L(Sdept,Sloc), S − D S-D S−D的码为Sno, D − L D-L D−L的码为Sdept。
在分解后的关系模式中既没有非主属性对码的部分函数依赖, 也没有非主属性对码的传递函数依赖,进一步解决了上述四个 问题。
💡解决依赖问题的办法:把一张大表拆成多个小表。
⭐️3NF关系模式的性质
- 若 R ∈ 3 N F R\in3NF R∈3NF,则** R R R的每一个非主属性既不部分函数依赖于候选码也不传递函数依赖于候选码**。
- 若 R ∈ 3 N F R\in3NF R∈3NF,则 R ∈ 2 N F R\in2NF R∈2NF。
- 采用投影分解法将一个 2 N F 2NF 2NF的关系分解为多个 3 N F 3NF 3NF的关系,可以在一 定程度上解决原 2 N F 2NF 2NF关系中存在的插入异常、删除异常、冗余度、修改复杂等问题。但依然并不能完全消除关系模式中的各种异常情况和数据冗余。
BC范式(BCNF)
是由Boyce和Codd提出的,比 3 N F 3NF 3NF更进了一步。通常认为 B C N F BCNF BCNF是修正的第三范式,有时也称为扩展的第三范式。
引入实例
仍然从一个例子来入手。关系模式 S T J ( S , T , J ) STJ(S,T,J) STJ(S,T,J)中, S S S表示学生, T T T表示教师, J J J表示课程。
先来分析一下语义(即从现实世界的情况入手来分析依赖):
-
假设每一教师只教一门课: T → J T→J T→J
-
假设每门课只由一个教师教,学生选定某门课,就能确定了一个固定的教师: ( S , J ) → T (S,J)→T (S,J)→T
- 学生选修某个教师的课就确定了所选课的名称: ( S , T ) → J (S,T)\rightarrow J (S,T)→J
⚠️这里我们一直都在用假设化简情况,自己仔细思考一下,可想而知现实世界中这样的依赖关系有多么复杂,这也就是范式这个东西的重要性所在。
在该例中, 候选码为 ( S , J ) (S,J) (S,J)和 ( S , T ) (S,T) (S,T) ,可见 S S S, T T T, J J J 都是主属性,不存在非主属性对码的部分函数依赖 和传递依赖,所以 S T J ∈ 3 N F STJ\in3NF STJ∈3NF。
虽然这是一个第三范式模型,但它仍存在增删改等异常,还不是一个理想的关系模式。
3NF中的问题
- 插入异常
如果某个教师开设了某门课程,但尚未有学生选修,则有关信息也无法存入数据库中。 - 删除异常
如果选修过某门课程的学生全部毕业了,在删除这些学生元组的同时,相应教师开设该门课程的信息也同时丢掉了。 - 数据冗余度大
虽然一个教师只教一门课,但每个选修该教师该门课程的学生元组都要记录这一信息。 - 修改复杂
某个教师开设的某门课程改名后,所有选修了该教师该门课程的学生元组都要进行相应修改。
问题原因
仔细观察,又是因为本该无关的数据之间存在依赖关系,需要再分解。即主属性 J J J部分依赖于码 ( S , T ) (S, T) (S,T)。因为 T → J T\rightarrow J T→J 。
⚠️3NF中主属性和主属性之间可能存在部分依赖。
解决办法
采用投影分解法,将 S T J STJ STJ分解为二个关系模式: S J ( S , J ) SJ(S,J) SJ(S,J)与 T J ( T , J ) TJ(T,J) TJ(T,J)。
这样 S J SJ SJ的码为 ( S , J ) (S,J) (S,J), T J TJ TJ的码为 T T T。
在分解后的关系模式中没有任何属性对码的部分函数依赖和传递函数依赖。 它解决了上述四个问题。
BCNF关系模式的性质
- 所有非主属性对每一个码都是完全函数依赖。
- 所有主属性对每一个不包含它的码也是完全函数依赖。
- 没有任何属性完全函数依赖于非码的任何一组属性。
💡全是完全依赖,全是码就完事了。
BCNF的意义
如果一个关系数据库中的所有关系模式都属于BCNF,那么在函数依赖范畴内,它已实现了模式的彻底分解,达到了最高的规范化程度,消除了操作异常诸多问题。
规范化总结
- 一个关系模式只要其分量都是不可分的数据项,它就是规范化的关系模式,但这只是最基本的规范化。
- 规范化程度过低的关系模式不一定能够很好地描述现实世界,可能会存在插入异常、删除异常、修改复杂、数据冗余等问题,解决方法就 是对其进行规范化,转换成高级范式。
- 一个低一级范式的关系模式,通过模式分解可以转换为若干个高一级范式的关系模式集合,这种过程就叫关系模式的规范化。
- 关系数据库的规范化理论是数据库逻辑设计的工具。
- 高级的关系模型必然包含低级的关系模型。
关系模型规范化基本步骤
规范化的基本思想
- 逐步消除数据依赖中不合适的部分,使模式中的各关系模式达到某种程度的“分离”。
- 采用“一事一地”的模式设计原则
让一个关系只描述一个概念、一个实体或者实体间的一种联系,若多于一个概念,就把它“分离”出去。 - 规范化实质上是概念的单一化。
🈚️数据依赖的公理系统
模式分解的理论基础是数据依赖的公理系统(ArmStrong公理系统),是一套推理规则。
模式分解
关系模式的规范化过程是通过对关系模式的模式分解来实现的。
模式分解的抽象定义
R < U , F > R<U,F> R<U,F>的一个分解是指:$\rho={R_1<U_1,F_1>, …, R_n<U_n,F_n>} , 其 中 , 其中 ,其中U=U_1\cup U_2\cup ···\cup U_n , 并 且 没 有 ,并且没有 ,并且没有U_i ⊆ U_J$, 1 ≤ i 1 ≤ i 1≤i, j ≤ n j ≤ n j≤n, F i F_i Fi 是 F F F在 U i U_i Ui 上的投影。
💡可以看到R, U被分解成了若干个小部分。
相应地将 R R R存储在二维表 r r r中的数据分散到二维表 r 1 , r 2 , … , r n r_1,r_2,… , r_n r1,r2,…,rn中去,其中 r i r_i ri是 r r r在属性集 U i U_i Ui上的投影。
模式分解三条准则
把低一级的关系模式分解为若干个高一级的关系模式并不是唯一的。在这些分解方法中,只有能够保证分解后的关系模式与原关系模式等价的方法才有意义,即模式分解三条准则:
- 分解具有无损连接性
- 分解要保持原有的函数依赖
- 分解既要保持函数依赖,又要具有无损连接性。
模式分解实例
还是以刚刚的关系模式 S − L ( S n o , S d e p t , S l o c ) S-L(Sno,Sdept,Sloc) S−L(Sno,Sdept,Sloc)为例,显然该关系模式存在一系列问题:
正确的模式分解
将 S − L S-L S−L分解为二个关系模式:
N D ( S n o , S d e p t ) , S n o → S d e p t ND(Sno, Sdept),Sno→Sdept ND(Sno,Sdept),Sno→Sdept
D L ( S d e p t , S l o c ) , S d e p t → S l o c DL(Sdept, Sloc),Sdept→Sloc DL(Sdept,Sloc),Sdept→Sloc
这种分解不仅保持函数依赖性, 还具有无损连接性。
💡用正常数据库开发的思维来考虑,也只能这样分。
错误的模式分解
应该来说除了刚刚提到的分解策略,其余都是错误的,归结一下错误分为以下几种:
-
既不具有无损连接性,也未保持函数依赖。
例如很极端的直接分解为3个关系模式 S N ( S n o ) , S D ( S d e p t ) , S O ( S l o c ) SN(Sno),SD(Sdept),SO(Sloc) SN(Sno),SD(Sdept),SO(Sloc)。 -
不具有无损连接性,但保持函数依赖。
例如分解为 N L ( S n o , S l o c ) , D L ( S d e p t , S l o c ) NL(Sno, Sloc),DL(Sdept, Sloc) NL(Sno,Sloc),DL(Sdept,Sloc), N L NL NL和 D L DL DL自然连接的结果为N L ⋈ D L NL⋈DL NL⋈DL比原来的 S − L S-L S−L关系多了三个元组,则无法知道原来的 S − L S-L S−L关系中究竟有哪些元组, 即此分解丢失了信息。
⚠️IS和PH系宿舍楼都在B导致的。 -
具有无损连接性,但未保持函数依赖。
例如分解为 N D ( S n o , S d e p t ) , N L ( S n o , S l o c ) ND(Sno, Sdept),NL(Sno, Sloc) ND(Sno,Sdept),NL(Sno,Sloc),没有考虑原函数依赖 S d e p t → S l o c Sdept→Sloc Sdept→Sloc。
这篇关于第一范式、第二范式、第三范式的区别(关系数据理论)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!