前言
说起三大范式,我脑海里第一反馈就是这几句话:
- 当实体 A 与实体 B 之间的关系是一对一时,会把实体 A 的主键作为 实体 B 的外键。当然关系是一对一时,反过来也能够,即把 实体 B 的主键当做实体 A 的外键;
- 当实体 A 与实体 B 之间的关系是一对多时,会把 A 的主键当做实体 B 的外键;
- 当实体 A 与实体 B 之间的关系是多对多时,通常会思考建一张新表来保留这两个实体之间的关系。
然而有时候实体与实体之间的关系并不是非常容易的看进去,所以靠这些了解并不足以设计出符合规范的表构造。在读了相应的材料后,发现自己对三大范式的了解是十分肤浅的、浮浅的,所以就写了这篇博客来记录本人对三大范式重新认识的过程。
什么是范式(NF)?
在了解三大范式之前,须要明确什么是范式(NF)?
依照教材中的定义,范式是:
合乎某一种级别的关系模式的汇合,示意一个关系外部各属性之间的分割的合理化水平。
能够了解为:一张数据表的表构造所合乎的某种设计标准的级别。
三大范式定义
以下是三大范式的定义:
- 第一范式:合乎
1NF
的关系中的每个属性都不可再分。 - 第二范式:
2NF
在1NF
的根底之上,打消了非主属性对于码的局部函数依赖。 - 第三范式:
3NF
在2NF
的根底之上,打消了非主属性对于码的传递函数依赖。
说实话,我一开始看到第二范式和第三范式的定义时,感到十分蛊惑:
- 什么是非主属性?
- 什么是码?
- 范式的定义为什么和函数无关?
然而在了解了这些概念之后,才意识到意识到这几条定义是如此的准确。
在了解“非主属性”和“码”之前,须要先彻底搞明确什么是“函数依赖”,因为“非主属性”和“码”的概念是建设在“函数依赖”的概念之上的。
什么是函数依赖?
若在一张表中,在属性(或属性组)X 的值确定的状况下,必然能确定属性 Y 的值,那么就能够说 Y 函数依赖于 X,写作 X → Y。
光看概念可能不太好了解什么是函数依赖,还是须要通过一个例子来了解。
学生表如下:
学号 | 姓名 | 性别 | 年龄 |
---|---|---|---|
1420233906 | 罗辑 | 男 | 21 |
1420233907 | 云天明 | 男 | 22 |
1420233908 | 章北海 | 男 | 23 |
1420233909 | 程心 | 女 | 20 |
这张学生表有四个属性:学号、姓名、性别、年龄。咱们晓得一个学号对应一个学生,如果你的班主任问你 1420233906 是谁,你就能够通知他 1420233906 是罗辑,除此之外,你还能通知你的班主任,罗辑是男的,21 岁。
换句话说:
- 在学号确定的状况下,就必然能确定姓名的值,即姓名 函数依赖于 学号,写作姓名 → 学号;
- 在学号确定的状况下,就必然能确定性别的值,即性别 函数依赖于 学号,写作性别 → 学号;
- 在学号确定的状况下,就必然能确定年龄的值,即年龄 函数依赖于 学号,写作年龄 → 学号;
还能在学生表中找到其余的函数依赖关系吗?答案是否定的。
如果学生表中,只有这四条记录,如同是能够通过姓名来确定学号、性别、年龄的值。然而在大多数班中必定存在 同名同姓 的学生,例如张伟:
学号 | 姓名 | 性别 | 年龄 |
---|---|---|---|
1420233906 | 罗辑 | 男 | 21 |
1420233907 | 云天明 | 男 | 22 |
1420233908 | 章北海 | 男 | 23 |
1420233909 | 程心 | 女 | 20 |
1420233909 | 张伟 | 男 | 21 |
1420233910 | 张伟 | 男 | 22 |
尽管同叫张伟,但却是两个不同的学生。当数学老师叫张伟时,两个张伟可能同时站起来。即在姓名确定的状况下,无奈确定学号的值,无奈确定性别的值也无奈确定年龄的值。同理:
- 在性别确认的状况下,无奈确定其余任意一个属性的值;
- 在年龄确认的状况下,无奈确定其余任意一个属性的值;
再来看一个更难的例子:
学号 | 姓名 | 系名 | 系主任 | 课名 | 分数 |
---|---|---|---|---|---|
1420233906 | 罗辑 | 机电工程系 | 艾 AA | 高等数学 | 99 |
1420233907 | 罗辑 | 机电工程系 | 艾 AA | 大学英语 | 98 |
1420233908 | 罗辑 | 机电工程系 | 艾 AA | 大学物理 | 97 |
1420233909 | 程心 | 经济系 | 维德 | 高等数学 | 88 |
1420233909 | 程心 | 经济系 | 维德 | 毛概 | 88 |
1420233910 | 程心 | 经济系 | 维德 | 大学英语 | 88 |
在这张表中存在哪些函数依赖关系呢?
- 学号 → 姓名
- 学号 → 系名(一个学生只属于一个系)
- 系名 → 系主任(一个系只有一个系主任)
- 学号 → 系主任(一个学生只属于一个系、一个系只有一个系主任,即在学号确定的状况下,必然能够确认该学生所属系的系主任)
- (学号,课名)→ 分数
然而以下函数依赖关系则不成立:
- 学号 → 课名
- 学号 → 分数
- 课名 → 分数
- …
从“函数依赖”这个概念开展,还会有三个概念:
1)齐全函数依赖
在一张表中,若 X → Y,且对于 X 的任何一个真子集(如果属性组 X 蕴含超过一个属性的话),X ‘ → Y 不成立,那么咱们称 Y 对于 X 齐全函数依赖,记作 X F→ Y
例如:(学号,课名)F→ 分数,即分数齐全函数依赖于(学号,课名)属性组。
- 属性 Y 要齐全函数依赖于属性(组)X 的前提是:属性 Y 要函数依赖于属性(组)X,分数函数依赖于(学号,课名),第一条满足;
- (学号,课名)是一个属性组,超过一个属性,它的真子集有{学号}、{课名},无奈只通过学号来确定分数,也无奈只通过课名来确定分数,故满足对于(学号、课名)的任何一个真子集,X’ → Y 不成立。
所以分数齐全函数依赖于(学号,课名)属性组成立。
2)局部函数依赖
如果 Y 函数依赖于 X,但同时 Y 并不齐全函数依赖于 X,那么咱们就称 Y 局部函数依赖于 X,记作 X P→ Y
例如:(学号,课名)P→ 姓名,即姓名局部函数依赖于(学号,课名)组。
- 首先姓名函数依赖于(学号,课名)属性组成立;
- (学号,课名)的真子集为{学号}、{课名},在这些真子集中,能够通过学号来确定姓名,即姓名函数依赖于学号,故姓名不齐全函数依赖于(学号,课名)属性组,即姓名局部函数依赖于(学号,课名)。
3)传递函数依赖
如果 Y 不蕴含于 X,且 X 不函数依赖于 Y,Z 函数依赖于 Y,且 Y 函数依赖于 X,那么咱们就称 Z 传递函数依赖于 X,记作 X T→ Z。
什么是码?
设 K 为某表中的一个属性或属性组,若除 K 之外的所有属性都齐全函数依赖于 K(这个“齐全”不要漏了),那么咱们称 K 为候选码,简称为码。
什么是非主属性
主属性之外的属性就是非主属性。
参考
- 第一范式、第二范式、第三范式详解 |☆☆☆☆☆
- 三张图搞透第一范式 (1NF)、第二范式(2NF) 和第三范式 (3NF) 的区别 |☆☆☆☆
- 真子集和子集有什么区别?|☆☆
- 数据库的三大范式(原理 + 例子详解)|☆☆☆