范式与数据库设计
- 数据之间存在依赖
- 函数依赖(FD):一个或一组属性可以决定其他属性的值
- 多值依赖:一个或一组属性可以决定其他属性的一组值,可以看出函数依赖是多值依赖的一种特殊情况。在实际应用中比较少见,一般可以不考虑
- 连接依赖:数据经过投影后,能够无损连接还原,则它们就存在连接依赖关系。举例:我要采购物品A,我和公司G有合同,G公司能够提供物品A,那我就一定要采购G公司的物品A。这样的情况就存在连接依赖。在实际应用中比较少见
- 范式理论
-
第一范式:表的属性必须是原子的,即不允许表中套表的情况。第一范式是关系模型固有的性质。尽管Oracle中有对象属性的概念,突破了第一范式
-
第二范式:满足第一范式,并且在属性间不存在部分函数依赖。举例:
S(S#, SNAME, AGE, ADDR, C#, GRADE),关系S 不满足第二范式,因为
(S#,C#)才是主键,而不是S#,但 SNAME, AGE, ADDR用S#就可以决定,即存在部分函数依赖
不满足第二范式带来的问题,还是上面的例子
- 插入异常:一门课都没选的学生的基本信息无法录入
- 删除异常:当学生退选所有课程后,他的基本信息也将丢失
- 由于数据的冗余,更新的时候很难保证数据的一致性
解决方式:
按照"one fact in one place",即一事一地的原则,将一张表拆分为两张表
-
第三范式:满足第二范式,并且属性间不存在传递函数依赖。举例:
EMP(EMP#, SAL_LEVEL, SALARY),EMP#可以决定SAL_LEVEL,SAL_LEVEL决定SALARY,即存在传递函数依赖
不满足第三范式带来的问题,还是上面雇员的例子:
-
插入异常:当一个公司的工资级别还未确定前,无法录入员工工资信息
-
Delete abnormity: if some sal_level has only one man,
the correspondence between sal_level and salary of
this level will be lost when the man is deleted. -
更新异常:因为存在大量的数据冗余,如3级工资对应5000,可能有100个人,当3级工资改为6000时,就所有数据都要改,即很难保证数据的一致性
解决方法还是一事一地原则。
-
-
BCNF范式:满足3NF,并且要求所有函数依赖中的决定子都必须是主键。
是3NF不是BCNF的例子:R(城市,街道,邮政编码),(城市,街道)是主键,可以决定邮政编码,反过来邮政编码可以决定城市(不能决定街道),但邮政编码不是主键,所以这个关系满足3NF,但不满足BCNF。BCNF可以认为是3NF的改进形式,BCNF基本可以认为与3NF是等价的,满足3NF,不满足BCNF的情况非常少。
-
在3NF的基础上消除多值依赖即4NF,在4NF的基础上消除连接依赖即5NF
- 数据库设计的两种方法
- 以流程为中心设计:能够快速实现,适合小和简单的系统,因为它没有分析数据间的内在联系,相当与把人工的过程快速在计算机系统里面模拟了一面
- 以数据为中心的设计:简单说,就是在流程的基础上,分析数据的内在联系
-
数据库设计流程
- 第一阶段,需求分析,需求分析包过信息需求和处理需求,最后得到需求说明文档
- 第二阶段,概念设计,这一阶段是与具体数据库系统无关的ER图设计
- 第三阶段,逻辑设计,这一阶段是结合具体数据库系统的特点,进行具体表结构的设计,如字段类型,还有视图等的设计,这一阶段的设计称为外模式
- 第四阶段,物理设计,这一阶段根据硬件和操作系统等的特点,考虑将数据以何种数据结构(如堆文件)存储到硬盘上,还包括索引等的设计,这一阶段的设计称为内模式
- 需求分析
需求分析需要解决的问题
- 命名冲突
- 概念冲突:同一个概念(如院系)可能是某个实体的一个属性,又可能是一个实体,所以要明确
- 取值范围冲突:如性别可能用男女表示,也可能用man woman表示
通过需求分析要保证任何信息都有明确的来源和责任
- 概念设计
- 定义实体
- 分析实体之间的联系
- 用工具画ER图,如ERWin Rose等工具
- 逻辑设计
- 逆规范化,遵守3NF可能导致表太小,从而导致过多的连接查询,导致查询效率低。所以要在规范化和效率之间找一个平衡
- 物理设计
- 结合DBMS内部实现技术,合理设计索引和文件结构,为查询优化准备好存储路径
- 数据库设计总结