设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。

目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。

此文章修改整理自: https://www.zhihu.com/question/24696366/answer/29189700

01. 一些概念

范式

范式是“符合某一种级别的关系模式的集合,表示一个关系内部各属性之间的联系的合理化程度”。实际上你可以把它粗略地理解为一张数据表的表结构所符合的某种设计标准的级别

关系 与 关系模式

“关系”和“关系模式”的区别,类似于面向对象程序设计中”类“与”对象“的区别。”关系“是”关系模式“的一个实例,你可以把”关系”理解为一张带数据的表,而“关系模式”是这张数据表的表结构。

元组

可以把“元组”理解为一张表中的每条记录,也就是每一行。

属性

关系里的列。

关系中的某个属性或者某几个属性的组合,用于区分每个元组。

主属性

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

异常

  • 插入异常:无法单独新添加一个系,因为每个系是伴随着学生而存在于这张表中的。
  • 删除异常:若将某个系中的全部学生记录都删掉,那么这个系也不复存在了。
  • 修改异常:假如李小明转系到法律系,那么为了保证数据库中数据的一致性,需要修改三条记录中系与系主任的数据。
  • 数据冗余:每一名学生的学号、姓名、系名、系主任这些数据重复多次。每个系与对应的系主任的数据也重复多次。

函数依赖

我们可以这么理解**:若在一张表中,在属性(或属性组)X 的值确定的情况下,必定能确定属性 Y 的值,那么就可以说 Y 函数依赖于 X,写作 X → Y**。也就是说,在数据表中,不存在任意两条记录,它们在 X 属性(或属性组)上的值相同,而在 Y 属性上的值不同。这也就是“函数依赖”名字的由来,类似于函数关系 y = f(x),在 x 的值确定的情况下,y 的值一定是确定的。

部分函数依赖

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

完全函数依赖

在一张表中,若 X → Y,且对于 X 的任何一个真子集(假如属性组 X 包含超过一个属性的话),X → Y 不成立,那么我们称 Y 对于 X 完全函数依赖

传递函数依赖

假如 Z 函数依赖于 Y,且 Y 函数依赖于 X (严格来说还有一个 X 不包含于 Y,且 Y 不函数依赖于 Z 的前提条件),那么我们就称 Z 函数传递依赖于 X 。

02. 1NF

定义: 符合 1NF 的关系中的每个属性都不可再分

上图中的表就不符合 1NF 的设计规范。

事实上,你在关系型数据库中创建的表,都一定满足 1NF 规范。类似于下面的表这样:

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

03. 2NF

定义: 2NF 在 1NF 的基础之上,消除了非主属性对于码的部分函数依赖

在上表中,学生信息与课程信息全混在了一张表中:

这里的码是 (学号,课名),用它来标识每个元组。

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

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

这时候需要对这张表进行拆分:

04. 3NF

定义: 3NF 在 2NF 的基础之上,消除了非主属性对于码的传递函数依赖

对于上图中的 选课 表,主码为**(学号,课名)**,主属性为 **学号** 和 **课名**,非主属性只有一个,为 **分数**,不可能存在传递函数依赖,所以 **选课** 表的设计,符合 3NF 的要求。

对于上图中的 学生 表,主码为 学号,主属性为 学号,非主属性为 姓名系名系主任。因为 学号 → 系名,同时 系名 → 系主任,所以存在非主属性 系主任 对于码 学号 的传递函数依赖,所以 学生 表的设计,不符合 3NF 的要求。

为了让数据表设计达到 3NF,我们必须进一步进行模式分解为以下形式: 选课(学号,课名,分数) 学生(学号,姓名,系名) (系名,系主任)

05. BCNF

若:

  1. 某公司有若干个仓库;
  2. 每个仓库只能有一名管理员,一名管理员只能在一个仓库中工作;
  3. 一个仓库中可以存放多种物品,一种物品也可以存放在不同的仓库中。每种物品在每个仓库中都有对应的数量。

基于此关系模式的关系(具体的数据)可能如图所示:

函数依赖集:仓库名 → 管理员,管理员 → 仓库名,(仓库名,物品名)→ 数量 :(管理员,物品名),(仓库名,物品名) 主属性 :仓库名、管理员、物品名 非主属性 :数量

∵ 此关系模式中不存在 非主属性 的 部分函数依赖 和 传递函数依赖。

∴ 此关系模式符合 3NF。

但是在某些特殊情况下,即使关系模式符合 3NF 的要求,仍然存在着插入异常,修改异常与删除异常等问题,仍然不是 “好” 的设计。

造成此问题的原因**:存在着 主属性 对于 码 的 部分函数依赖 与 传递函数依赖。在此例中就是存在主属性 仓库名 对于码的部分函数依赖。**

解决办法就是要在 3NF 的基础上消除 主属性 对于 码 的部分与传递函数依赖:

仓库(仓库名,管理员) 库存(仓库名,物品名,数量)