关于mysql:三大范式再认识

前言

说起三大范式,我脑海里第一反馈就是这几句话:

  • 当实体 A 与实体 B 之间的关系是一对一时,会把实体 A 的主键作为 实体 B 的外键。当然关系是一对一时,反过来也能够,即把 实体B 的主键当做实体 A 的外键;
  • 当实体 A 与实体 B 之间的关系是一对多时,会把 A 的主键当做实体 B 的外键;
  • 当实体 A 与实体 B 之间的关系是多对多时,通常会思考建一张新表来保留这两个实体之间的关系。

然而有时候实体与实体之间的关系并不是非常容易的看进去,所以靠这些了解并不足以设计出符合规范的表构造。在读了相应的材料后,发现自己对三大范式的了解是十分肤浅的、浮浅的,所以就写了这篇博客来记录本人对三大范式重新认识的过程。

什么是范式(NF)?

在了解三大范式之前,须要明确什么是范式(NF)?

依照教材中的定义,范式是:

合乎某一种级别的关系模式的汇合,示意一个关系外部各属性之间的分割的合理化水平。

能够了解为:一张数据表的表构造所合乎的某种设计标准的级别

三大范式定义

以下是三大范式的定义:

  • 第一范式:合乎 1NF 的关系中的每个属性都不可再分。
  • 第二范式:2NF1NF 的根底之上,打消了非主属性对于码的局部函数依赖。
  • 第三范式:3NF2NF 的根底之上,打消了非主属性对于码的传递函数依赖。

说实话,我一开始看到第二范式和第三范式的定义时,感到十分蛊惑:

  • 什么是非主属性?
  • 什么是码?
  • 范式的定义为什么和函数无关?

然而在了解了这些概念之后,才意识到意识到这几条定义是如此的准确。

在了解“非主属性”和“码”之前,须要先彻底搞明确什么是“函数依赖”,因为“非主属性”和“码”的概念是建设在“函数依赖”的概念之上的。

什么是函数依赖?

若在一张表中,在属性(或属性组)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 为候选码,简称为码。

什么是非主属性

主属性之外的属性就是非主属性。

参考

  1. 第一范式、第二范式、第三范式详解|☆☆☆☆☆
  2. 三张图搞透第一范式(1NF)、第二范式(2NF)和第三范式(3NF)的区别|☆☆☆☆
  3. 真子集和子集有什么区别?|☆☆
  4. 数据库的三大范式(原理 + 例子详解)|☆☆☆

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理