一、三范式

注:设计只是一种思想一种理念,我们按照规范的设计方式设计数据库对我们来说有好处,但绝对不是说一定要严格遵守,三范式能极大的**减少数据冗余,但是相对编写sql而言是增加了难度的,所以所有好的设计都是要权衡利弊的,要对编码难度,存储大小,执行效率等多方面进行综合考量,但是在学习初期最好紧紧的遵循三范式,在后续的编码中体会和总结自己的经验。

设计数据库表的时候所依据的规范,共三个规范:

1
2
3
第一范式:要求有主键,并且要求每一个字段原子性不可再分
第二范式:要求所有非主键字段完全依赖主键,不能产生部分依赖
第三范式:所有非主键字段和主键字段之间不能产生传递依赖

1、第一范式

数据库表中不能出现重复记录,每个字段是原子性的不能再分

不符合第一范式的实例:

学生编号 学生姓名 联系方式
1001 白杰 bj@qq.com,18565987896
1002 杨春旺 ycw@qq.com,13659874598
1003 张志伟 zzw@qq.com,12598745698

解决方案

学生编号 学生姓名 邮箱地址 联系电话
1001 白杰 bj@qq.com 18565987896
1002 杨春旺 ycw@qq.com 13659874598
1003 张志伟 zzw@qq.com 12598745698

不符合第一范式的实例,不是说他错哈:

学生编号 学生姓名 联系地址
1001 白杰 太原市尖草坪区恒山路108号
1002 杨春旺 太原市迎泽区迎泽大家100号
1003 张志伟 太原市杏花岭区北大街152号

解决方案:

学生编号 学生姓名 详细地址
1001 白杰 太原市 尖草坪区 恒山路108号
1002 杨春旺 太原市 迎泽区 迎泽大街100号
1003 张志伟 太原市 杏花岭区 北大街152号

必须有主键,这是数据库设计的最基本要求,主要采用数值型或定长字符串表示,关于列不可再分,应该根据具体的情况来决定。如联系方式,为了开发上的便利可能就采用一个字段。

关于第一范式,每一行必须唯一,也就是每个表必须有主键,这是数据库设计的最基本要求,主要采用数值型或定长字符串表示,关于列不可再分,应该根据具体的情况来决定。如联系方式,为了开发上的便利可能就采用一个字段。

2、第二范式

第二范式是建立在第一范式基础上的,另外要求所有非主键字段完全依赖主键,不能产生部分依赖

不符合第二范式的案例:

其中学生编号和课程编号为联合主键

学生编号 性别 学生姓名 课程编号 课程名称 教室 成绩
1001 白杰 2001 java 3004 89
1002 杨春旺 2002 mysql 3003 88
1003 刘慧慧 2003 html 3005 90
1001 白杰 2002 mysql 3003 77
1001 白杰 2003 html 3005 89
1003 刘慧慧 2001 java 3004 90

以上虽然确定了主键,但此表会出现大量的数据冗余,出现冗余的原因在于,学生信息部分依赖了主键的一个字段学生编号,和课程id没有毛线关系。同时课程的信息只是依赖课程id,和学生id没有毛线关系。只有成绩一个字段完全依赖主键的两个部分,这就是第二范式部分依赖

解决方案:

学生表:学生编号为主键

学生编号 性别 学生姓名
1001 白杰
1002 杨春旺
1003 刘慧慧

课程表:课程编号为主键

课程编号 课程名称 教室
2001 java 3003
2002 mysql 3003
2003 html 3005

成绩表:学生编号和课程编号为联合主键

学生编号 课程编号 成绩
1001 2001 89
1002 2002 88
1003 2003 90
1001 2002 77
1001 2003 89
1003 2001 90

如果一个表是单一主键,那么它就是复合第二范式,部分依赖和主键有关系

以上是典型的“多对多”设计

#3、第三范式

建立在第二范式基础上的,非主键字段不能传递依赖于主键字段(不要产生传递依赖)

不满足第三范式的例子:

其中学生编号是主键

学生编号 学生姓名 专业编号 专业名称
1001 白杰 2001 计算机
1002 杨春旺 2002 自动化
1003 张志伟 2001 计算机

何为传递依赖?

专业编号依赖学生编号,因为该学生学的就是这个专业啊。但是专业名称和学生其实没多大关系,专业名称依赖于专业编号。这就叫传递依赖,就是某一个字段不直接依赖主键,而是依赖 依赖主键的另一个字段。

解决方法:

学生表,学生编号为主键:

学生编号为主键:

学生编号 学生姓名 专业编号
1001 白杰 2001
1002 杨春旺 2002
1003 张志伟 2001

专业表,专业编号为主键:

专业编号 专业名称
2001 计算机
2002 自动化

以上设计是典型的一对多的设计,一存储在一张表中,多存储在一张表中,在多的那张表中添加外键指向一的一方

#二、常见表关系

#1、一对一 用的不多

一个表和另一张表存在的关系是一对一,此种设计不常用,因为此种关系经常会将多张表合并为一张表。

举例:

学生信息表可以分为基本信息表和详细信息表。

可能有这种需求,需要给个某个账户对学生表的操作,但是有些私密信息又不能暴露,就可以拆分。

1
2
第一种方案:分两张表存储,共享主键
第二种方案:分两张表存储,外键唯一

#2、一对多

第三范式的例子

两张表 外键建在多的一方

1
2
分两张表存储,在多的一方添加外键,
这个外键字段引用一的一方中的主键字段

#3、多对多

第二范式的例子

1
2
分三张表存储,在学生表中存储学生信息,在课程表中存储课程信息,
在成绩表中存储学生和课程的关系信息