阅读 269

第一范式、第二范式、第三范式的区别(关系数据理论)

关系数据理论

使用关系数据库理论来进行关系数据库的逻辑设计,简单来说就是针对一个具体问题,使用关系数据理论来构造适合于它的数据库模式

⭐️数据依赖

数据依赖是一个关系内部属性与属性之间的一种约束关系。通过属性间值的相等与否体现出来的。是现实世界属性间相互联系的抽象,是数据内在的性质,是语义的体现。 数据依赖最重要的是函数依赖(Functional Dependency,FD)和多值依赖(Multi- Valued Dependency,MVD)

函数依赖

函数依赖普遍存在于现实生活中,例如描述一个学生的关系,有学号(Sno)、姓名(Sname)、系名(Sdept)等属性。现实世界中,一个学生对应一个学生,一个学生只属于一个系,因而学号确定后,学生所在的系也就确定了,这就称为一个函数依赖。记作SnoSdeptSno \rightarrow Sdept(读作Sno决定Sdept)。 💡简单理解为Sno和Sdept之间存在某种函数对应关系。

函数依赖不是指关系模式R的某些关系满足的约束条件,而是指R的一切关系均要满足的约束条件的集合

函数依赖相关术语

  • XYX \rightarrow Y,则称XX为这个函数依赖的决定属性组,又称决定因素,读作XX决定YY。 ⚠️X、Y是属性或者属性集,XYX \rightarrow YYY依赖XXXX决定YY

  • XYX \rightarrow Y,但YXY \nsubseteq X,则称XYX \rightarrow Y非平凡的函数依赖。 ⚠️XYX \subseteq YYY包含XX

  • XYX \rightarrow Y,但YXY \subseteq X,则称XYX \rightarrow Y平凡的函数依赖。对于任一关系模式,平凡的函数依赖均必然成立,不反映新的语义(没什么用,一般不考虑)。

  • ⭐️在R(U)R(U)中,如果XYX \rightarrow Y,并且对于XX的任何一个真子集XX^{'},都有XYX^{'} \nrightarrow Y,则称YYXX完全函数依赖,记作XFYX\stackrel{F}{\longrightarrow}Y。 💡只有XX整个集合才能决定YY成为完全函数依赖,存在XX中的一子属性决定YY称为部分函数依赖。

    • ⭐️同理,若XYX \rightarrow Y,但YY不完全依赖于XX,则称**YYXX部分函数依赖**,记作XPYX\stackrel{P}{\longrightarrow}Y
  • R(U)R(U)中,如果XYX \rightarrow YYZY \rightarrow ZYX,YX,ZYY \nrightarrow X, Y \nsubseteq X,Z \nsubseteq Y),则称Z对X传递函数依赖,记作X传递YX\stackrel{传递}{\longrightarrow}Y

    image-20210322114203235

    这个地方的概念必须得看懂。

码的函数依赖定义

  • KKR<U,F>R<U,F>中的属性火属性组合,若KFUK \stackrel{F}{\longrightarrow} U,即UU完全函数依赖于KK,则称KKRR候选码若候选码多于一个,选定其中一个为主码
  • 如果UU部分函数依赖于KK,则称KK超码。候选码是最小的超码,即KK的任一真子集都不是候选码。
  • 包含在候选码中的属性成为主属性,否则称为非主属性。整个属性组全是码,称为全码
image-20210322114050048

🈚️多值依赖

范式与规范化

规范化要讨论一个模式的数据依赖会有哪些不好的性质,以及如何改造一个不好的模式。一个低一级范式的关系模式通过模式分解可以转换为若干个高一级范式的关系模式的集合,这种过程就叫规范化

范式表示关系的某一级别,常称某一关系模式RR为第几范式,RR为第几范式可以写成RxNFR \in xNF,各种范式之间的关系为5NF4NFBCNF3NF2NF1NF5NF \in 4NF \in BCNF\in 3NF \in 2NF \in 1NF

第一范式

关系作为一个二维表,要符合一个最基本的条件:每一个分量必须是不可分的数据项(表不能有子表)。满足了这个条件的关系模式就属于第一范式(1NF)

第二范式

R1NFR∈1NF,且每一个非主属性==完全函数依赖==于任何一个候选码,则称为第二范式,记作R2NFR∈2NF。 2NF通过消除部分函数依赖,可以在一定程度上减轻1NF中存在的插入异常、删除异常、数据冗余大、修改复杂等问题,但并不能完全消除关系模式的各种异常情况和数据冗余。

第三范式(3NF)

我们抛开形式化的定义,直接从一个例子入手来理解。

2NF回顾

例如,2NF采用投影分解法,把SLCS-L-C解为两个关系模式SCSCSLS-L消除了SLCS-L-C中非主属性对码的部分函数依赖。

image-20210321162816984

💡简单来说就是再拆分几张表出来,让表中只剩下完全依赖,部分依赖是一切问题的根源。

按照这种方法把1NF关系模式分解为多个2NF的关系模式,可以减轻1NF关系模式中存在的插入异常、删除异 常、数据冗余度大、修改复杂等问题,但并不能完全消除关系模式中的各种异常情况和数据冗余。

2NF中的问题

例如,在SL(Sno,Sdept,Sloc)S-L(Sno, Sdept, Sloc)关系模型中,SlocSloc依赖于SdeptSdeptSdeptSdept又依赖于SnoSno,即SLS-L中存在非主属性对码的传递函数依赖Sno传递SlocSno\stackrel{传递}{\longrightarrow}Sloc

image-20210321165234427

然而,这其中存在的问题有:

  1. 插入异常 如果某个系暂时没有在校学生,我们就无法把这个系的信息存入数据库。

  2. 删除异常 如果某个系的学生全部毕业了,我们在删除该系全部学生信息的同时,就把这个系的信息也丢掉了。

  3. 数据冗余度大 每一个系的学生都住在同一个地方,按理来说只存一次就行了,但关于在每个学生信息里,该系的住处的信息却重复出现。

  4. 修改复杂 学校调整学生住处时,由于刚刚提到的关于每个系的住处信息是重复存储的,修改时必须同时更新该系所有学生的SlocSloc属性值。

问题原因

SLS-LSlocSloc传递函数依赖于SnoSno, 即非主属性传递函数依赖码。 💡可见非主依赖这个东西是一切问题的根源。

2NF问题的解决办法

依然是采用投影分解法,把SLS-L分解为两个 关系模式,以消除传递函数依赖: SDSnoSdeptS-D(Sno, Sdept)DLSdeptSlocD-L(Sdept, Sloc)SDS-D的码为Sno, DLD-L的码为Sdept。

image-20210321174528969

在分解后的关系模式中既没有非主属性对码的部分函数依赖, 也没有非主属性对码的传递函数依赖,进一步解决了上述四个 问题。 💡解决依赖问题的办法:把一张大表拆成多个小表。

⭐️3NF关系模式的性质

  • R3NFR\in3NF,则**RR的每一个非主属性既不部分函数依赖于候选码也不传递函数依赖于候选码**。
  • R3NFR\in3NF,则R2NFR\in2NF
  • 采用投影分解法将一个2NF2NF的关系分解为多个3NF3NF的关系,可以在一 定程度上解决原2NF2NF关系中存在的插入异常、删除异常、冗余度、修改复杂等问题。但依然并不能完全消除关系模式中的各种异常情况和数据冗余。

BC范式(BCNF)

是由Boyce和Codd提出的,比3NF3NF更进了一步。通常认为BCNFBCNF是修正的第三范式,有时也称为扩展的第三范式

引入实例

仍然从一个例子来入手。关系模式STJSTJSTJ(S,T,J)中,SS表示学生,TT表示教师,JJ表示课程。 先来分析一下语义(即从现实世界的情况入手来分析依赖):

  1. 假设每一教师只教一门课:TJT→J

  2. 假设每门课只由一个教师教,学生选定某门课,就能确定了一个固定的教师:SJT(S,J)→T

    1. 学生选修某个教师的课就确定了所选课的名称: (ST)J(S,T)\rightarrow J

    ⚠️这里我们一直都在用假设化简情况,自己仔细思考一下,可想而知现实世界中这样的依赖关系有多么复杂,这也就是范式这个东西的重要性所在。

    image-20210321203639514

在该例中, 候选码为(SJ)(S,J)(ST)(S,T) ,可见SSTTJJ 都是主属性,不存在非主属性对码的部分函数依赖 和传递依赖,所以STJ3NFSTJ\in3NF

虽然这是一个第三范式模型,但它仍存在增删改等异常,还不是一个理想的关系模式。

3NF中的问题

  1. 插入异常 如果某个教师开设了某门课程,但尚未有学生选修,则有关信息也无法存入数据库中。
  2. 删除异常 如果选修过某门课程的学生全部毕业了,在删除这些学生元组的同时,相应教师开设该门课程的信息也同时丢掉了。
  3. 数据冗余度大 虽然一个教师只教一门课,但每个选修该教师该门课程的学生元组都要记录这一信息。
  4. 修改复杂 某个教师开设的某门课程改名后,所有选修了该教师该门课程的学生元组都要进行相应修改。

问题原因

仔细观察,又是因为本该无关的数据之间存在依赖关系,需要再分解。即主属性JJ部分依赖于码(S,T)(S, T)。因为TJT\rightarrow J 。 ⚠️3NF中主属性和主属性之间可能存在部分依赖。

解决办法

采用投影分解法,将STJSTJ分解为二个关系模式:SJ(SJ)SJ(S,J)TJ(TJ)TJ(T,J)。 这样SJSJ的码为(SJ)(S,J)TJTJ的码为TT

image-20210321204805386

在分解后的关系模式中没有==任何属性==对码的部分函数依赖和传递函数依赖。 它解决了上述四个问题。

BCNF关系模式的性质

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

💡全是完全依赖,全是码就完事了。

BCNF的意义

如果一个关系数据库中的所有关系模式都属于BCNF,那么在函数依赖范畴内,它已实现了模式的彻底分解,达到了==最高的规范化程度==,消除了操作异常诸多问题

规范化总结

  • 一个关系模式只要其分量都是不可分的数据项,它就是规范化的关系模式,但这只是最基本的规范化。
  • 规范化程度过低的关系模式不一定能够很好地描述现实世界,可能会存在插入异常、删除异常、修改复杂、数据冗余等问题,解决方法就 是对其进行规范化,转换成高级范式。
  • 一个低一级范式的关系模式,通过模式分解可以转换为若干个高一级范式的关系模式集合,这种过程就叫关系模式的规范化
  • 关系数据库的规范化理论是数据库逻辑设计的工具。
  • 高级的关系模型必然包含低级的关系模型。

关系模型规范化基本步骤

image-20210321210137393

规范化的基本思想

  • 逐步消除数据依赖中不合适的部分,使模式中的各关系模式达到某种程度的“分离”
  • 采用“一事一地”的模式设计原则 让一个关系只描述一个概念、一个实体或者实体间的一种联系,若多于一个概念,就把它“分离”出去。
  • 规范化实质上是概念的单一化

🈚️数据依赖的公理系统

模式分解的理论基础是数据依赖的公理系统(ArmStrong公理系统),是一套推理规则。

模式分解

关系模式的规范化过程是通过对关系模式的模式分解来实现的。

模式分解的抽象定义

R<U,F>R<U,F>的一个分解是指:ρ=R1<U1,F1>,,Rn<Un,Fn>\rho={R_1<U_1,F_1>, …, R_n<U_n,F_n>} , 其中U=U1U2UnU=U_1\cup U_2\cup ···\cup U_n,并且没有UiUJU_i ⊆ U_J1i1 ≤ ijnj ≤ nFiF_iFFUiU_i 上的投影。 💡可以看到R, U被分解成了若干个小部分。 相应地将RR存储在二维表rr中的数据分散到二维表 r1r2,rnr_1,r_2,… , r_n中去,其中rir_irr在属性集UiU_i上的投影。

模式分解三条准则

把低一级的关系模式分解为若干个高一级的关系模式并不是唯一的。在这些分解方法中,只有能够保证分解后的关系模式与原关系模式等价的方法才有意义,即模式分解三条准则

  • 分解具有无损连接性
  • 分解要保持原有的函数依赖
  • 分解既要保持函数依赖,又要具有无损连接性。

模式分解实例

还是以刚刚的关系模式SL(Sno,Sdept,Sloc)S-L(Sno,Sdept,Sloc)为例,显然该关系模式存在一系列问题:

image-20210321165234427

正确的模式分解

SLS-L分解为二个关系模式: ND(Sno,Sdept),SnoSdeptND(Sno, Sdept),Sno→Sdept

DL(Sdept,Sloc),SdeptSlocDL(Sdept, Sloc),Sdept→Sloc 这种分解不仅保持函数依赖性, 还具有无损连接性。 💡用正常数据库开发的思维来考虑,也只能这样分。

错误的模式分解

应该来说除了刚刚提到的分解策略,其余都是错误的,归结一下错误分为以下几种:

  • 既不具有无损连接性,也未保持函数依赖。 例如很极端的直接分解为3个关系模式SN(Sno),SD(Sdept),SO(Sloc)SN(Sno),SD(Sdept),SO(Sloc)

  • 不具有无损连接性,但保持函数依赖。 例如分解为NL(Sno,Sloc),DL(Sdept,Sloc)NL(Sno, Sloc),DL(Sdept, Sloc)NLNLDLDL自然连接的结果为

    image-20210322144422955

    NLDLNL⋈DL比原来的SLS-L关系多了三个元组,则无法知道原来的SLS-L关系中究竟有哪些元组, 即此分解丢失了信息。 ⚠️IS和PH系宿舍楼都在B导致的。

  • 具有无损连接性,但未保持函数依赖。 例如分解为ND(Sno,Sdept),NL(Sno,Sloc)ND(Sno, Sdept),NL(Sno, Sloc),没有考虑原函数依赖SdeptSlocSdept→Sloc

文章分类
后端
文章标签