本文主要讨论表的设计。
设计表的时候会遵守一些规则,这些规则被称为三大范式,范式是描述数据关系的模型;实体之间也有其对应关系:一对一关系,一对多关系和多对多关系。
分类:第一范式 1NF、第二范式 2NF、第三范式 3NF、BC范式 BCNF。
第一范式(1NF)
关系型数据库的一个最基本的要求,不满足第一范式就不可以称为关系型数据库。
第一范式的字段满足在表里的字段不可进行再拆分。
在定义表的时候,对照到数据中的数据类型;每一个字段都可以用一个数据类型表示,那么当前这个表就满足第一范式。
例如,在一个学生表中,字段名为:

以上的字段中每个都是不可再分的,这样的字段就满足了第一范式。而如果是:

而学校又继续分为学校名、地址、电话等等,这样还可在分的就不满足第一范式。
第二范式(2NF)
在满足第一范式的基础上,不存在非关键字段对任意候选键的部分函数依赖(存在于复合主键的情况下)。
什么意思呢?我们利用学生表的例子来理解:
成绩表
学号 学生姓名 年龄 课程 学分 成绩
已知 成绩 是通过 学号 和 课程 两个组成的复合主键来确定的,成绩 会依赖于 学号 和 课程 两个字段;
而学生的姓名、年龄等字段依赖于学号,与课程没有关系;同样的,课程的学分等依赖于课程,与学号没有关系;
像上面这种情况,对于由两个或多个关键字段决定一条记录的情况下,如果一行数据中有些字段至于关键字段中的一个有关系,那么这种情况就是 只存在部分函数依赖。
如果出现上面的情况,那么该表就不满足第二范式。
那么如何设计才能使表满足第二范式?就要让每个字段和全部主键都有依赖:
学生表
学号 姓名 年龄
课程表
课程编号 课程 学分
学生成绩表
学号 课程编号 成绩
如上的方式中,每个表中都不会出现部分依赖的情况,通过分成三个表,就能成功满足第二范式。
所以说,如果表中不是复合主键,即只有一列作为主键,那么这样的表一定满足第二范式。
如果不满足第二范式会出现什么问题?
1、数据冗余
2、更新异常
如果在更新中途数据库出现某些问题导致更新失败,就会使得一些数据在修改前一些是修改后导致数据混乱。
3、插入异常
以成绩表为例,学生的名字和年龄对成绩这个字段是没有意义的。
4、删除异常
如果学生毕业,删除学生记录的同时也会将对应课程的字段(例如学分)也全部删除掉了。
第三范式(3NF)
在第二范式的基础上,不存在非关键字段,对任意一个候选键的传递依赖。
我们同样使用学生表的例子:
学生表
学号 姓名 年龄 所在学院 学院地址 学院电话
我们可以通过这个表看出以下的传递关系:
学号 -> 所在学院 -> 学院地址、电话
这样的传递关系就是传递依赖。而这种表就不是第三范式,因为存在传递依赖。
同样地,要满足第三范式,我们拆分为两个表即可:
学院表
学院编号 学院名 学院地址 学院电话
学生表
学号 姓名 年龄 学院编号
第三范式可以解决数据冗余,更新异常,插入异常和删除异常的问题。
对应关系
1、一对一关系
类似于用户和账号的关系。
一个用户只有一个账号,而一个账号也对应着一个用户。
表与表之间的一对一关系如下:A表中的一条记录,最多值对应B表中的一条记录;反过来也是一样。
针对一对一关系,在设计表时有两种方式:
- 把两个实体所有的信息全都放在一张表里。
- 创建两张表,例如分别记录用户信息和账号信息,并将这两张表关联。

2、一对多关系
类似于学生和班级的关系。
一个学生只能存在于一个班级,而一个班级可以有多个学生。设计时如下:

通过学生记录中的class_id可以表示学生所在的班级。
3、多对多关系
多对多类似于学生和课程的关系。
一个学生可以选修多门课程;而一门课程也对应选择了的多个学生。
设计表时有两种方式:
- 分别创建实体表
- 创建关系表,在关系表中为实体之间创建关联关系