Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >第一范式、第二范式、第三范式、BCNF范式详解

第一范式、第二范式、第三范式、BCNF范式详解

作者头像
全栈程序员站长
发布于 2022-08-31 13:35:32
发布于 2022-08-31 13:35:32
5.1K0
举报

大家好,又见面了,我是你们的朋友全栈君。

文章目录


0. 范式(NF)

按照教材中的定义,范式是“符合某一种级别的关系模式的集合,表示一个关系内部各属性之间的联系的合理化程度”。很晦涩吧?实际上你可以把它粗略地理解为一张数据表的表结构所符合的某种设计标准的级别。就像家里装修买建材,最环保的是E0级,其次是E1级,还有E2级等等。数据库范式也分为1NF,2NF,3NF,BCNF,4NF,5NF。一般在我们设计关系型数据库的时候,最多考虑到BCNF就够。符合高一级范式的设计,必定符合低一级范式,例如符合2NF的关系模式,必定符合1NF。

接下来就对每一级范式进行一下解释。

1. 第一范式(1NF)

符合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:码:关系中的某个属性或者某几个属性的组合,用于区分每个元组(可以把“元组”理解为一张表中的每条记录,也就是每一行)。
  1. 假如将某个系中所有学生相关的记录都删除,那么所有系与系主任的数据也就随之消失了(一个系所有学生都没有了,并不表示这个系就没有了)。——删除异常
  2. 假如李小明转系到法律系,那么为了保证数据库中数据的一致性,需要修改三条记录中系与系主任的数据。——修改异常

正因为仅符合1NF的数据库设计存在着这样那样的问题,我们需要提高设计标准,去掉导致上述四种问题的因素,使其符合更高一级的范式(2NF),这就是所谓的“规范化”。

2. 第二范式(2NF)

在关系理论中的严格定义我这里就不多介绍了(因为涉及到的铺垫比较多),只需要了解2NF对1NF进行了哪些改进即可。其改进是,2NF在1NF的基础之上,消除了非主属性对于码的部分函数依赖。接下来对这句话中涉及到的四个概念——“函数依赖”、“码”、“非主属性”、与“部分函数依赖”进行一下解释。

2.1 函数依赖

我们可以这么理解(但并不是特别严格的定义):若在一张表中,在属性(或属性组)X的值确定的情况下,必定能确定属性Y的值,那么就可以说Y函数依赖于X,写作 X → Y。也就是说,在数据表中,不存在任意两条记录,它们在X属性(或属性组)上的值相同,而在Y属性上的值不同。这也就是“函数依赖”名字的由来,类似于函数关系 y = f(x),在x的值确定的情况下,y的值一定是确定的。 例如,对于表3中的数据,找不到任何一条记录,它们的学号相同而对应的姓名不同。所以我们可以说姓名函数依赖于学号,写作 学号 → 姓名。但是反过来,因为可能出现同名的学生,所以有可能不同的两条学生记录,它们在姓名上的值相同,但对应的学号不同,所以我们不能说学号函数依赖于姓名。表中其他的函数依赖关系还有如:

系名 → 系主任学号 → 系主任 (学号,课名) → 分数

但以下函数依赖关系则不成立:

学号 → 课名 学号 → 分数 课名 → 系主任 (学号,课名) → 姓名

从“函数依赖”这个概念展开,还会有三个概念:

2.1.1完全函数依赖

在一张表中,若 X → Y,且对于 X 的任何一个真子集(假如属性组 X 包含超过一个属性的话),X ’ → Y 不成立,那么我们称 Y 对于 X 完全函数依赖,记作 X F→ Y。(那个F应该写在箭头的正上方,没办法打出来……,正确的写法如图1

图1

例如: 学号 F→ 姓名 (学号,课名) F→ 分数 (注:因为同一个的学号对应的分数不确定,同一个课名对应的分数也不确定)

2.1.2 部分函数依赖

假如 Y 函数依赖于 X,但同时 Y 并不完全函数依赖于 X,那么我们就称 Y 部分函数依赖于 X,记作 X P→ Y,如图2。

图2

例如:(学号,课名) P→ 姓名

2.1.3 传递函数依赖

假如 Z 函数依赖于 Y,且 Y 函数依赖于 X ,那么我们就称 Z 传递函数依赖于 X ,记作 X T→ Z,如图3。

图3

2.2 码

设 K 为某表中的一个属性或属性组,若除 K 之外的所有属性都完全函数依赖于 K(这个“完全”不要漏了),那么我们称 K 为候选码,简称为码。在实际中我们通常可以理解为:假如当 K 确定的情况下,该表除 K 之外的所有属性的值也就随之确定,那么 K 就是码。一张表中可以有超过一个码。(实际应用中为了方便,通常选择其中的一个码作为主码) 例如:对于表3,(学号、课名)这个属性组就是码。该表中有且仅有这一个码。(假设所有课没有重名的情况)

2.3 非主属性

包含在任何一个码中的属性成为主属性。

例如: 对于表3,主属性就有两个,学号 与 课名。

终于可以回过来看2NF了。首先,我们需要判断,表3是否符合2NF的要求?根据2NF的定义,判断的依据实际上就是看数据表中是否存在非主属性对于码的部分函数依赖。若存在,则数据表最高只符合1NF的要求,若不存在,则符合2NF的要求。判断的方法是:

第一步:找出数据表中所有的码。 第二步:根据第一步所得到的码,找出所有的主属性。 第三步:数据表中,除去所有的主属性,剩下的就都是非主属性了。 第四步:查看是否存在非主属性对码的部分函数依赖。

对于表3,根据前面所说的四步,我们可以这么做:

第一步:

  1. 查看所有每一单个属性,当它的值确定了,是否剩下的所有属性值都能确定。
  2. 查看所有包含有两个属性的属性组,当它的值确定了,是否剩下的所有属性值都能确定。
  3. ……
  4. 查看所有包含了六个属性,也就是所有属性的属性组,当它的值确定了,是否剩下的所有属性值都能确定。

看起来很麻烦是吧,但是这里有一个诀窍,就是假如A是码,那么所有包含了A的属性组,如(A,B)、(A,C)、(A,B,C)等等,都不是码了(因为作为码的要求里有一个“完全函数依赖”)。 图4表示了表中所有的函数依赖关系:

图4

这一步完成以后,可以得到,表3的码只有一个,就是 (学号、课名) 。

第二步:主属性有两个:学号 与 课名

第三步:非主属性有四个:姓名、系名、系主任、分数

第四步: 对于(学号,课名) → 姓名,有 学号 → 姓名,存在非主属性 姓名 对码(学号,课名)的部分函数依赖。 对于(学号,课名) → 系名,有 学号 → 系名,存在非主属性 系名 对码(学号,课名)的部分函数依赖。 对于(学号,课名) → 系主任,有 学号 → 系主任,存在非主属性 对码(学号,课名)的部分函数依赖。

所以表3存在非主属性对于码的部分函数依赖,最高只符合1NF的要求,不符合2NF的要求。

为了让表3符合2NF的要求,我们必须消除这些部分函数依赖,只有一个办法,就是将大数据表拆分成两个或者更多个更小的数据表,在拆分的过程中,要达到更高一级范式的要求,这个过程叫做”模式分解“。模式分解的方法不是唯一的,以下是其中一种方法: 选课(学号,课名,分数) 学生(学号,姓名,系名,系主任)

我们先来判断以下,选课表与学生表,是否符合了2NF的要求?

对于选课表,其码是(学号,课名),主属性是学号和课名,非主属性是分数,学号确定,并不能唯一确定分数,课名确定,也不能唯一确定分数,所以不存在非主属性分数对于码 (学号,课名)的部分函数依赖,所以此表符合2NF的要求。

对于学生表,其码是学号,主属性是学号,非主属性是姓名、系名和系主任,因为码只有一个属性,所以不可能存在非主属性对于码 的部分函数依赖,所以此表符合2NF的要求。 图5表示了模式分解以后的新的函数依赖关系

图5

表4表示了模式分解以后新的数据

表4

(这里还涉及到一个如何进行模式分解才是正确的知识点,先不介绍了) 现在我们来看一下,进行同样的操作,是否还存在着之前的那些问题?

  1. 李小明转系到法律系 只需要修改一次李小明对应的系的值即可。——有改进
  2. 数据冗余是否减少了? 学生的姓名、系名与系主任,不再像之前一样重复那么多次了。——有改进
  3. 删除某个系中所有的学生记录 该系的信息仍然全部丢失。——无改进
  4. 插入一个尚无学生的新系的信息。 因为学生表的码是学号,不能为空,所以此操作不被允许。——无改进

所以说,仅仅符合2NF的要求,很多情况下还是不够的,而出现问题的原因,在于仍然存在非主属性系主任对于码学号的传递函数依赖。为了能进一步解决这些问题,我们还需要将符合2NF要求的数据表改进为符合3NF的要求。

3. 第三范式(3NF)

3NF在2NF的基础之上,消除了非主属性对于码的传递函数依赖。也就是说, 如果存在非主属性对于码的传递函数依赖,则不符合3NF的要求。 接下来我们看看表4中的设计,是否符合3NF的要求。 对于选课表,主码为(学号,课名),主属性为学号和课名,非主属性只有一个,为分数,不可能存在传递函数依赖,所以选课表的设计,符合3NF的要求。 对于学生表,主码为学号,主属性为学号,非主属性为姓名、系名和系主任。因为 学号 → 系名,同时 系名 → 系主任,所以存在非主属性系主任对于码学号的传递函数依赖,所以学生表的设计,不符合3NF的要求。 为了让数据表设计达到3NF,我们必须进一步进行模式分解为以下形式: 选课(学号,课名,分数) 学生(学号,姓名,系名) 系(系名,系主任) 对于选课表,符合3NF的要求,之前已经分析过了。 对于学生表,码为学号,主属性为学号,非主属性为系名,不可能存在非主属性对于码的传递函数依赖,所以符合3NF的要求。 对于系表,码为系名,主属性为系名,非主属性为系主任,不可能存在非主属性对于码的传递函数依赖(至少要有三个属性才可能存在传递函数依赖关系),所以符合3NF的要求。。 新的函数依赖关系如图6

图6

新的数据表如表5

表5

现在我们来看一下,进行同样的操作,是否还存在着之前的那些问题?

  1. 删除某个系中所有的学生记录 该系的信息不会丢失。——有改进
  2. 插入一个尚无学生的新系的信息。 因为系表与学生表目前是独立的两张表,所以不影响。——有改进
  3. 数据冗余更加少了。——有改进

结论 由此可见,符合3NF要求的数据库设计,基本上解决了数据冗余过大,插入异常,修改异常,删除异常的问题。当然,在实际中,往往为了性能上或者应对扩展的需要,经常 做到2NF或者1NF,但是作为数据库设计人员,至少应该知道,3NF的要求是怎样的。

4. BCNF范式

要了解 BCNF 范式,那么先看这样一个问题: 若: 某公司有若干个仓库;每个仓库只能有一名管理员,一名管理员只能在一个仓库中工作; 一个仓库中可以存放多种物品,一种物品也可以存放在不同的仓库中。每种物品在每个仓库中都有对应的数量。 那么关系模式 仓库(仓库名,管理员,物品名,数量) 属于哪一级范式? 答:已知函数依赖集:仓库名 → 管理员,管理员 → 仓库名,(仓库名,物品名)→ 数量 码:(管理员,物品名),(仓库名,物品名) 主属性:仓库名、管理员、物品名非主属性:数量 ∵ 不存在非主属性对码的部分函数依赖和传递函数依赖。 ∴ 此关系模式属于3NF。 基于此关系模式的关系(具体的数据)可能如图所示:

好,既然此关系模式已经属于了 3NF,那么这个关系模式是否存在问题呢?我们来看以下几种操作: 先新增加一个仓库,但尚未存放任何物品,是否可以为该仓库指派管理员?——不可以,因为物品名也是主属性,根据实体完整性的要求,主属性不能为空。 某仓库被清空后,需要删除所有与这个仓库相关的物品存放记录,会带来什么问题?——仓库本身与管理员的信息也被随之删除了。 如果某仓库更换了管理员,会带来什么问题?——这个仓库有几条物品存放记录,就要修改多少次管理员信息。 从这里我们可以得出结论,在某些特殊情况下,即使关系模式符合 3NF 的要求,仍然存在着插入异常,修改异常与删除异常的问题,仍然不是 ”好“ 的设计。 造成此问题的原因:存在着主属性对于码的部分函数依赖与传递函数依赖。(在此例中就是存在主属性【仓库名】对于码【(管理员,物品名)】的部分函数依赖。 解决办法就是要在 3NF 的基础上消除主属性对于码的部分与传递函数依赖。 仓库(仓库名,管理员) 库存(仓库名,物品名,数量) 这样,之前的插入异常,修改异常与删除异常的问题就被解决了。 以上就是关于 BCNF 的解释。

问:关于码的定义,如果除K之外的所有属性都完全函数依赖于K时才能称K为码,那么在判断2NF时又怎么会存在非主属性对码的部分函数依赖这种情况?

答 :在“码”的定义中,除 K 之外的所有属性应该看成是一个集合 U(也就是一个整体),也就是说,只有 K 能够完全函数决定 U 中的每一个属性,那么 K 才是码。如果 K 只是能够完全函数决定 U 中的一部分属性,而不能完全函数决定另外一部分属性,那么 K 不是码。 比如有关系模式 R (Sno, Sname, Cno, Cname, Sdept, Sloc, Grade),其中函数依赖集为 F= {Sno → Sname, Sno → Sdept, Sdept → Sloc,Sno → Sloc, Cno → Cname, (Sno, Cno) → Grade } 那么 R 中的码只能是 (Sno, Cno),Sno 或 Cno 并不能完全函数决定除 Sno / Cno 之外的所有其他属性(其实就是不能决定 Grade ),所以单独的 Sno 与 Cno 并不能作为码。 所以可得到主属性:Sno, Cno 非主属性:Sname, Cname, Sdept, Sloc, Grade R 中存在非主属性 Cname 对于码 (Sno, Cno) 的部分函数依赖 (Cno → Cname) 。(还有很多别的例子就不一一列举了)。所以 R 不符合 2NF 的要求。

5. 小结

1NF: 字段是最小的的单元不可再分 2NF:满足1NF,表中的字段必须完全依赖于全部主键而非部分主键 (一般我们都会做到) 3NF:满足2NF,非主键外的所有字段必须互不依赖4NF:满足3NF,消除表中的多值依赖

6. 参考文献

数据库范式那些事

详解第一范式、第二范式、第三范式、BCNF范式

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/142158.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年5月2,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
MySQL (4) 第一范式 第二范式 第三范式 BC范式
第一范式:所有属性都是不可分割的原子值。 也就是每个属性都是不可再分的。 例如下图就不符合第一范式的要求
全栈程序员站长
2022/08/31
1.2K0
MySQL (4) 第一范式 第二范式 第三范式 BC范式
第二范式和bcnf范式区别(bcnf范式通俗解释)
建立在第一范式的基础上,每一个非主属性要完全函数依赖于候选键(或者说是主键,任一个候选键都可以做主键)。即非主键列完全依赖于主键,而不能是依赖于主键的一部分,必须满足两个条件:
全栈程序员站长
2022/08/01
9610
第一范式、第二范式和第三范式「建议收藏」
概念:设计数据库是,需要遵循的一些规范,要遵循后边的范式要求,必须遵循前边的所有范式要求
全栈程序员站长
2022/08/31
1.5K0
第一范式,第二范式,第三范式,BCNF范式理解
实体:现实世界中客观存在并可以被区别的事物。比如“一个学生”、“一本书”、“一门课”等等。值得强调的是这里所说的“事物”不仅仅是看得见摸得着的“东西”,它也可以是虚拟的,比如说“老师与学校的关系”。
全栈程序员站长
2022/08/25
1.3K0
第一范式,第二范式,第三范式,BCNF范式理解
数据库的范式(第一范式,第二范式,第三范式,BCNF范式)「建议收藏」
能够唯一标识元组的某一属性或属性组,任何包含超码的超集也是超码,这里唯一标识元组可以简单的理解为根据某一个字段或几个字段的值,查询出某一行特定的数据
全栈程序员站长
2022/07/31
1.4K0
[数据库] 第一范式、第二范式、第三范式、BC范式
关键码 1) 超键:在关系中能唯一标识元组的属性或属性集称为关键模式的超键。 2) 候选键:不含有多余属性的超键称为候选键。也就是在候选键中在删除属性就不是键了。 3) 主键:用户选作元组标识的候选键称为主键。一般不加说明,键就是指主键。 4) 外键:如果模式R中属性K是其他模式的主键,那么K在模式R中称为外键。
全栈程序员站长
2022/08/31
8390
[数据库] 第一范式、第二范式、第三范式、BC范式
数据库 部分函数依赖 完全函数依赖 传递函数依赖 第一范式、第二范式、第三范式、BCNF范式区别
数据库 部分函数依赖 完全函数依赖 传递函数依赖 第一范式、第二范式、第三范式、BCNF范式区别
全栈程序员站长
2022/08/31
2.4K0
数据库 部分函数依赖 完全函数依赖 传递函数依赖 第一范式、第二范式、第三范式、BCNF范式区别
数据库系统概述——第六章 关系数据理论(知识点复习+练习题)
函数依赖的定义:设R(U)是一个属性集U上的关系模式,X和Y是U的子集。若对于R(U)的任意一个可能的关系r,r中不可能存在两个元组在X上的属性值相等, 而在Y上的属性值不等, 则称 “X函数确定Y” 或 “Y函数依赖于X”,记作X→Y。即只要 X 上的属性值相等,Y 上的值一定相等。
命运之光
2024/03/20
6080
数据库系统概述——第六章 关系数据理论(知识点复习+练习题)
数据库的第一范式,第二范式,第三范式,BCNF范式理解
所谓的第一范式就是数据库中的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性,如果出现重复的属性则需要重新构建实体,新的实体由重复的属性构成。 见图
全栈程序员站长
2022/08/31
9620
数据库的第一范式,第二范式,第三范式,BCNF范式理解
关系模型的相关术语[通俗易懂]
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/106918.html原文链接:https://javaforall.cn
全栈程序员站长
2022/08/04
1.4K0
数据库范式
empno ename deptno 其中empno就能唯一标示一行数据了,是码(empno=1的只有一行数据)
九转成圣
2024/04/10
1600
数据库范式
关系型数据库设计三大范式
百度百科:设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
爬格子PA
2024/12/23
2310
关系型数据库设计三大范式到底是什么?
百度百科:设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
java干货
2021/02/04
1.1K0
关系型数据库设计三大范式到底是什么?
数据库设计——关系数据理论(超详细)「建议收藏」
●关系型数据库逻辑设计: ➠针对一个具体问题应如何构造一个适合于它的数据模式,即应构造几个关系,每个关系由哪些属性组成等 eg:
全栈程序员站长
2022/11/07
1.1K0
数据库设计——关系数据理论(超详细)「建议收藏」
软考高级架构师:数据库的范式 1NF 、2NF 、3NF 和 BCNF
数据库范式是一系列规范条件的集合,这些规范条件定义了数据库表结构的合理性,以减少数据冗余和改善数据的逻辑结构。主要的范式包括第一范式(1NF)、第二范式(2NF)、第三范式(3NF)和巴斯-科德范式(BCNF)。每个高级范式都建立在前一个范式的基础上。
明明如月学长
2024/05/25
7780
软考高级架构师:数据库的范式 1NF 、2NF 、3NF 和 BCNF
举例说明一下怎么算是第一范式、第二范式、第三范式?
数据库的设计范式是数据库设计所需要满足的规范,满足这些规范的数据库是简洁的、结构明晰的,同时,不会发生插入(insert)、删除(delete)和更新(update)操作异常。反之则是乱七八糟,不仅给数据库的编程人员制造麻烦,而且面目可憎,可能存储了大量不需要的冗余信息。
全栈程序员站长
2022/08/31
5660
数据库“三大范式”及“事务性”详解
在进行比较正规的项目开发的时候,通常会根据需求设计相应的数据库,而这些数据库则通常需要考虑数据库的冗余性和简洁性,数据库三大范式就是对关系数据库设计结构的一个规定。
灰小猿
2022/05/05
6980
数据库泛型(三范式)
数据库的设计范式是数据库设计所需要满足的规范,满足这些规范的数据库是简洁的、结构明晰的,同时,不会发生插入(insert)、删除(delete)和更新(update)操作异常。反之则是乱七八糟,不仅给数据库的编程人员制造麻烦,而且面目可憎,可能存储了大量不需要的冗余信息。
vv彭
2020/10/27
8470
数据库设计
举个例子: 按上面出现过的图, Students(sid, Iname, fname, midiaitia)
Rikka
2022/01/19
3.3K0
数据库设计
MySQL数据库——数据库的设计(多表之间的关系与三大范式)与备份还原
数据库中存放很多表,设计数据库就是设计表,而表就是对现实事物的抽象,设计数据库,需要明白表的关系,也要知道数据库的设计准则,即范式。数据库设计的好坏关系到项目开发效率与运行的好坏。
Winter_world
2020/09/25
3.9K0
MySQL数据库——数据库的设计(多表之间的关系与三大范式)与备份还原
推荐阅读
相关推荐
MySQL (4) 第一范式 第二范式 第三范式 BC范式
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档