天天看点

Mysql系列——数据库设计(3)——数据库设计的三大范式:详细OneTwoThree

在大学学习数据库的时候,不明白为什么会学习很多关系代数、设计范式的理论。但是,有了这些理论基础,在遇到问题的时候脑袋会有灵光一闪的感觉。那种感觉很像是大雾天太阳照射大地的感觉,心中一片光亮。^_^

那么,范式是什么呢?

课本中的定义:范式是“符合某一种级别的关系模式的集合,表示一个关系内部各属性之间的联系的合理化程度”。–《数据库理论》

通俗的讲,他是一套成型的设计原则,照着这种原则设计数据库能够少走弯路。

接下来,简单的介绍下三个范式。

One

1NF的定义为:符合1NF的关系中的每个属性都不可再分。下表所示的情况,就不符合1NF的要求。

Mysql系列——数据库设计(3)——数据库设计的三大范式:详细OneTwoThree

:引用自知乎

同样的,下表中也不符合1NF:

用户id 用户名 所属角色id
1 user1 2,5,9

一般来说上边的用户表的方式较为常见,我在刚毕业编程的时候,曾经有朋友交给我这种方式,也让我吃了一些苦头。

下表符合第一范式:

编号 品名 进货数量 进货单价 销售数量 销售单价 备注

用户表:

用户id 用户名
1 user1

用户角色关系表

用户id 角色id
1 2
1 5
1 9

Two

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

函数依赖:

我们可以这么理解(但并不是特别严格的定义):若在一张表中,在属性(或属性组)X的值确定的情况下,必定能确定属性Y的值,那么就可以说Y函数依赖于X,写作 X → Y。

码:能够确定表中所有其他字段值的字段或者字段组合。

对于下表中的数据,找不到任何一条记录,它们的学号相同而对应的姓名不同。所以我们可以说姓名函数依赖于学号,写作 学号 → 姓名。但是,其中(学号,课程)->分数,就是说学号跟课程才能确定分数。

因此我们首先选取表中的码。就是通过表中所有属性的依赖关系(决定关系)来确定码。

学号->姓名

学号->系名

学号,课程->分数

因此,能够决定所有其他属性的字段或者字段组合是(学号,课程)字段组合,选取该组合为码。

那么,对于码(学号,课程)来说,学号,课程->姓名属于部分函数依赖,因为码(学号,课程)的部分属性学号就能确定姓名这个属性。

学号 姓名 系名 课程 分数
002001 王明 地理信息学院 大学数学 95
002001 王明 地理信息学院 大学英语 92
002003 张芳 地理信息学院 计算机基础 96

因此上表不能满足第二范式,如果不能满足范式,可以通过拆表来解决:

学号 姓名 系名
002001 王明 地理信息学院

学号->姓名

学号->系名

学号 课程 分数
002001 大学数学 95
002001 大学英语 92

学号,课程->分数

那么现在上表满足第二范式了,仍然不满足第三范式。试想下,如果该系更名,那么就需要修改学生表中的所有系名。请看:数据库三大范式-引出

用数据库的专业属于,学号-> 系名属于传递依赖,因为学号->系编号 ->系名。

由此引出第三范式:

Three

第三范式(3NF) 3NF在2NF的基础之上,消除了非主属性对于码的传递函数依赖。

那么下表中,学号->系名属于传递依赖,不满足第三范式。

学号 姓名 系名
002001 王明 地理信息学院

同样,如果某个表不满足第三范式,通过拆表来解决。将传递依赖进行拆除,放到新的表中。

如下:

学号 姓名 系编号
002001 王明 002
系编号 系名
002 地理信息学院

那么为什么,我们将系编号添置在学生表中作为一个属性,而不像下面两张表一样再写一个关系表呢?

学号 系编号
002001 002
学号 姓名
002001 王明

因为学生:学院 之间是1:M,就是说是1对多的关系。如果您对实体表之间的关系感兴趣,请看下一节。

由于,博客增加了一些内容,因此进行了延期。对此,明义经典感到很抱歉。亲,请见谅啊。

继续阅读