Database Normal Form

#范式:


#第一范式

指数据库表的每一列都是不可分割的基本数据项 在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库。

#第二范式:

数据库表中不存在非关键字段对任一候选键的部分函数依赖,也即所有非关键字段都完全依赖于任意一组候选关键字。

2NF的违例只会出现在候选键由超过一个字段构成的表中,因为对单关键字字段不存在部分依赖问题。

例子:(学号, 姓名, 年龄, 课程名称, 成绩, 学分)

候选键只有一个,就是(姓名,课程名称),则主键就是(姓名,课程名称)

存在如下决定关系:

1:(学号, 课程名称) → (姓名, 年龄, 成绩, 学分)

2:(课程名称) → (学分)

3:(学号) → (姓名, 年龄)

其中,姓名、年龄、学分是部分依赖于主键的,而成绩是完全依赖于主键的,存在部分依赖关系,所以不满足第二范式。

这会造成如下问题

(1) 数据冗余:

同一门课程由n个学生选修,"学分"就重复n-1次;同一个学生选修了m门课程,姓名和年龄就重复了m-1次。

(2) 更新异常:

若调整了某门课程的学分,数据表中所有行的"学分"值都要更新,否则会出现同一门课程学分不同的情况。

(3) 插入异常:

假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有"学号"关键字,课程名称和学分也无法记录入数据 库。

(4) 删除异常:

假设一批学生已经完成课程的选修,这些选修记录就应该从数据库表中删除。但是,与此同 时,课程名称和学分信息也被删除了。很显然,这也会导致插入异常。

问题就在于存在非主属性对主键的部分依赖

解决办法:把原表(学号, 姓名, 年龄, 课程名称, 成绩, 学分)分成三个表:

学生:Student(学号, 姓名, 年龄);

课程:Course(课程名称, 学分);

选课关 系:SelectCourse(学号, 课程名称, 成绩)。

#第三范式:

在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式

出现传递依赖A->B->C,即主键A可以确定出某一非关键字段B,而B又可以确定出C,这意味着C依赖于一个非关键字段B。因此第三范式又可描述为:表中不存在可以确定其他非关键字的非键字段

例子:表:(学号, 姓名, 年龄, 所在学院, 学院地点, 学院电话)

该表中候选字段只有“学号”,于是“学号”做主键。由于主键是单一属性,所以不存在非主属性对主键的部分函数依赖的问题,所以必然满足第二范式。但是存在如下传递依赖

(学号) → (所在学院) → (学院地点, 学院电话)

学院地点和学院电话传递依赖于学号,而学院地点和学院电话都是非关键字段,即表中出现了“某一非关键字段可以确定出其它非关键字段”的情况,于是违反了第三范式。

解决办法:

把原表分成两个表:

学生:(学号, 姓名, 年龄, 所在学院);

学院:(学院, 地点, 电话)。

#BCNF:

BCNF意味着在关系模式中每一个决定因素都包含候选键,也就是说,只要属性或属性组A能够决定任何一个属性B,则A的子集中必须有候选键。BCNF范式排除了任何属性(不光是非主属性,2NF和3NF所限制的都是非主属性)对候选键的传递依赖与部分依赖。