概念
• 必须保证数据库设计的合理性
数据库设计关系整个系统的架构,关系到后续开发效率和运行效率
数据库的设计主要包含了设计表结构和表之间的联系
• 如何是合理数据库
结构合理
冗余较小
尽量避免插入删除修改异常
• 如何才能保证数据库设计水平
遵循一定的规则
在关系型数据库中这种规则就称为范式
• 什么是范式(NF= NormalForm)
范式是符合某一种设计要求的总结。
要想设计一个结构合理的关系型数据库,必须满足一定的范式。
第一范式(1NF)
字段具有原子性,不可再分。所有关系型数据库系统都满足第一范式
数据库表中的字段都是单一属性的,不可再分
。例如,姓名字段,其中的姓和名必须作为一个整体,无法区分哪部分是姓,哪部分是名,如果要区分出姓和名,必须设计成两个独立的字段。
• 要求
- 最基本的范式
- 数据库表每一列都是不可分割基本数据项,同一列中不能有多个值
- 简单说就是要确保每列保持原子性
- 第一范式的合理遵循需要根据系统的实际需求来定
• 示例
- 用户表(用户名,家庭地址)
- 用户表(用户名,省,城市,详细地址)
- 系(系名称,系主任,系高级职称人数)
- 系(系名称,系主任,系教授人数,系副教授人数)
第二范式(2NF):
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。
要求数据库表中的每个实例或行必须可以被惟一地区分
。通常需要为表加上一个列,以存储各个实例的惟一标识。这个惟一属性列被称为主键或主键。
第二范式(2NF)要求实体的属性完全依赖于外键。所谓完全依赖是指不能存在仅依赖主键一部分的属性,如果存在,那么这个属性和主键的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。简而言之,第二范式就是非主属性非部分依赖于主键。
• 要求
- 第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。
- 即在一个数据库表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
• 示例
- 学号和课程编号作为联合主键
- 课程名称只依赖于课程编号,而和学号没有关系
• 解决 - 提取出学生表
- 提取成课程表
- 提取选课表,存放选课记录
第三范式:
满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主键信息
。
所以第三范式具有如下特征:
1,每一列只有一个值
2,每一行都能区分。
3,每一个表都不包含其他表已经包含的非主键信息。
例如,帖子表中只能出现发帖人的id,而不能出现发帖人的id,还同时出现发帖人姓名,否则,只要出现同一发帖人id的所有记录,它们中的姓名部分都必须严格保持一致,这就是数据冗余。
• 要求
- 确保数据表中的每一列数据都和主键直接相关,而不能间接相关
- 属性不依赖于其他非主属性。
• 示例1:学生班级表
学号(主键) | 学生姓名 | 班级编号 | 班级名称 | 班级信息 |
---|---|---|---|---|
023145 | 张三 | 987654 | 3班 | 特招班 |
023146 | 李四 | 987654 | 3班 | 特招班 |
023147 | 王五 | 987655 | 4班 | 普通班 |
023258 | 赵六 | 987654 | 3班 | 特招班 |
完善之后的方案:
学号(主键) | 学生姓名 | 班级编号 |
---|---|---|
023145 | 张三 | 987654 |
023146 | 李四 | 987654 |
023147 | 王五 | 987655 |
023258 | 赵六 | 987654 |
班级编号(主键) | 班级名称 | 班级信息 |
---|---|---|
987654 | 3班 | 特招班 |
987655 | 4班 | 普通班 |
• 示例2:订单明细表
编号(主键) | 图书id | 图书名称 | 价格 | 作者 | 出版社 | 出版日期 | 数量 |
---|---|---|---|---|---|---|---|
023145 | 1 | 精通Java | 60.00 | 张三 | 清华出版社 | 2007 | 1 |
023146 | 2 | Oracle | 65.00 | 李四 | 机械出版社 | 2009 | 1 |
023147 | 3 | JSP | 87 | 王五 | 电子出版社 | 2014 | 3 |
023258 | 1 | 精通Java | 60.00 | 张三 | 清华出版社 | 2007 | 2 |
023259 | 2 | Oracle | 65.00 | 李四 | 机械出版社 | 2009 | 3 |
完善之后的方案:分割成图书表和订单表两种表
图书id | 图书名称 | 价格 | 作者 | 出版社 | 出版日期 |
---|---|---|---|---|---|
1 | 精通Java | 60.00 | 张三 | 清华出版社 | 2007 |
2 | Oracle | 65.00 | 李四 | 机械出版社 | 2009 |
3 | JSP | 87 | 王五 | 电子出版社 | 2014 |
4 | Struts2 | 56 | 赵六 | 清华出版社 | 2005 |
编号(主键) | 图书id | 数量 |
---|---|---|
023145 | 1 | 1 |
023146 | 2 | 1 |
023147 | 3 | 3 |
023258 | 2 | 2 |
023259 | 2 | 3 |
范式的优缺点
• 优点
- 结构合理
- 冗余较小
- 尽量避免插入删除修改异常
• 缺点
- 性能降低
- 多表查询比单表查询速度慢
- 数据库的设计应该根据当前情况和需求做出灵活的处理。
- 在实际设计中,要整体遵循范式理论。
- 如果在某些特定的情况下还死死遵循范式也是不可取的,因为可能降低数据库的效率,此时可以适当增加冗余而提高性能。
• 示例:
比如经常购物车条目的中除了条目编号,商品编号,商品数量外,可以增加经常使用的商品名称,商品价格等
图书表
图书id | 图书名称 | 价格 | 作者 | 出版社 | 出版日期 |
---|---|---|---|---|---|
1 | 精通Java | 60 | 张三 | 清华出版社 | 2007 |
2 | Oracle宝典 | 65 | 李四 | 机械出版社 | 2009 |
3 | JSP | 87 | 王五 | 电子出版社 | 2014 |
4 | Struts2 | 56 | 赵六 | 清华出版社 | 2005 |
订单表中增加冗余列图书名称、价格,以空间换时间。
编号(主键) | 图书id | 图书名称 | 价格 | 数量 |
---|---|---|---|---|
023145 | 1 | 精通Java | 60 | 1 |
023146 | 2 | Oracle宝典 | 65 | 1 |
023147 | 3 | JSP | 87 | 3 |
023258 | 1 | 精通Java | 60 | 2 |
小结
• 范式是指导数据设计的规范化理论,可以保证数据库设计质量
• 第一范式:字段不能再分
• 第二范式:不存在局部依赖
• 第三范式:不含传递依赖(间接依赖)
• 使用范式可以减少冗余,但是会降低性能
• 特定表的的设计可以违反第三范式,增加冗余提高性能