下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922

数据库三范式基础详解

作者:课课家教育the     来源: http://www.kokojia.com点击数:778发布时间: 2017-08-31 09:00:14

标签: 数据库数据库设计数据库范式

  数据库的设计范式是数据库设计所需要满足的规范,满足这些规范的数据库是简洁的、结构明晰的,同时,不会发生插入(insert)、删除(delete)和更新(update)操作异常。反之则是乱七八糟,不仅给数据库的编程人员制造麻烦,而且面目可憎,可能存储了大量不需要的冗余信息。

  什么是范式:简言之就是,数据库设计对数据的存储性能,还有开发人员对数据的操作都有莫大的关系。所以建立科学的,规范的的数据库是需要满足一些

  规范的来优化数据数据存储方式。在关系型数据库中这些规范就可以称为范式。

  什么是范式:简言之就是,数据库设计对数据的存储性能,还有开发人员对数据的操作都有莫大的关系。所以建立科学的,规范的的数据库是需要满足一些    规范的来优化数据数据存储方式。在关系型数据库中这些规范就可以称为范式。

  范式说明

  1.第一范式(1NF)无重复的列

  所谓第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能同时有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系。在第一范式(1NF)中表的每一行只包含一个实例的信息。简而言之,第一范式就是无重复的列。

  在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库。在当前的任何关系数据库管理系统(DBMS)中,不可能做出不符合第一范式的数据库,因为这些DBMS不允许你把数据库表的一列再分成二列或多列。因此,你想在现有的DBMS中设计出不符合第一范式的数据库都是不可能的。

  举例1:

  一张学生表Student(stuNo,stuName,age,age,sex)是不符合第一范式的,因为有重复列age属性。去除重复列age以后的Student(stuNo,stuName,age,sex)是符合第一范式的。

  2.第二范式(2NF)属性完全依赖于主键[消除部分子函数依赖]

  在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖)

  第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或记录必须可以被唯一地区分。选取一个能区分每个实体的属性或属性组,作为实体的唯一标识。例如在员工表中的身份证号码即可实现每个一员工的区分,该身份证号码即为候选键,任何一个候选键都可以被选作主键。在找不到候选键时,可额外增加属性以实现区分,如果在员工关系中,没有对其身份证号进行存储,而姓名可能会在数据库运行的某个时间重复,无法区分出实体时,设计辟如ID等不重复的编号以实现区分,被添加的编号或ID选作主键。(该主键的添加是在ER设计时添加,不是建库时随意添加)

  第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。简而言之,第二范式就是属性完全依赖于主键。

  这里说的主关键字可能不只有一个,有些情况下是存在联合主键的,就是主键有多个属性。

  举例2:

  以学生选课为例,每个学生都可以选课,并且有这一门课程的成绩,那么如果将这些信息都放在一张表StuGrade(stuNo,stuName,age,sex,courseNo,courseName,credit,score)。

 第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。简而言之,第二范式就是属性完全依赖于主键。    这里说的主关键字可能不只有一个,有些情况下是存在联合主键的,就是主键有多个属性。    举例2:    以学生选课为例,每个学生都可以选课,并且有这一门课程的成绩,那么如果将这些信息都放在一张表StuGrade(stuNo,stuName,age,sex,courseNo,courseName,credit,score)。

  如果不仔细看,我们会以为这张表的主键是stuNo,但是当我们看到最后一个score属性以后,在想想如果没有课程信息,那么哪里有学生成绩信息呢。所以这张表的主键是一个联合主键(stuNo,corseNo),这个联合属性能够唯一确定score属性。那么再看其他信息,比如stuName只需要stuNo就能够唯一确定,courseName只需要courseNo就能够唯一确定,因此这样就存在了部分依赖,不符合第二范式。如果要让学生课程成绩信息满足第二范式,那么久需要将这张表拆分成多张表,一张学生表Studnet(stuNo,stuName,age,sex),一张课程表Course(courseNo,courseName,credit),还有最后一张学生课程成绩表StuGrade(stuNo,courseNo,score)。

 如果不仔细看,我们会以为这张表的主键是stuNo,但是当我们看到最后一个score属性以后,在想想如果没有课程信息,那么哪里有学生成绩信息呢。所以这张表的主键是一个联合主键(stuNo,corseNo),这个联合属性能够唯一确定score属性。那么再看其他信息,比如stuName只需要stuNo就能够唯一确定,courseName只需要courseNo就能够唯一确定,因此这样就存在了部分依赖,不符合第二范式。如果要让学生课程成绩信息满足第二范式,那么久需要将这张表拆分成多张表,一张学生表Studnet(stuNo,stuName,age,sex),一张课程表Course(courseNo,courseName,credit),还有最后一张学生课程成绩表StuGrade(stuNo,courseNo,score)。

  这样就符合第二范式了。

  3.第三范式(3NF)属性不依赖于其它非主属性[消除传递依赖]

  在1NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)

  第三范式(3NF)是第二范式(2NF)的一个子集,即满足第三范式(3NF)必须满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个关系中不包含已在其它关系已包含的非主关键字信息。例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。简而言之,第三范式就是属性不依赖于其它非主属性,也就是在满足2NF的基础上,任何非主属性不得传递依赖于主属性。

  举例3:

  每一个员工都有一个所属部门,假如有一个员工信息表Employee(emp_id,emp_name,emp_age,dept_id,dept_name,dept_info)。

在1NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)    第三范式(3NF)是第二范式(2NF)的一个子集,即满足第三范式(3NF)必须满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个关系中不包含已在其它关系已包含的非主关键字信息。例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。简而言之,第三范式就是属性不依赖于其它非主属性,也就是在满足2NF的基础上,任何非主属性不得传递依赖于主属性。    举例3:    每一个员工都有一个所属部门,假如有一个员工信息表Employee(emp_id,emp_name,emp_age,dept_id,dept_name,dept_info)。

  这张员工信息表的主键是emp_id,因为这个属性能够唯一确定其他所有属性,比如知道员工编号emp_id以后,肯定能够知道员工姓名,所属部门编号,部门名称和部门介绍。所以这里dept_id不是主属性,而是非主属性。但是,我们又可以发现dept_name,dept_info这两个属性也可以由dept_id这个非主属性决定,即dept_name依赖dept_id,而dept_id依赖emp_id,这样就存在了传递依赖。而且我们可以看出传递依赖的一个明显缺点就是数据冗余非常严重。

  那么如何解决传递依赖问题,其实非常简单,我们只需要将dept_name,dept_info这连个属性删除就可以了,即Employee(emp_id,emp_name,emp_age,dept_id),然后再创建一个部门表Dept(dept_id,dept_name,dept_info)。

这张员工信息表的主键是emp_id,因为这个属性能够唯一确定其他所有属性,比如知道员工编号emp_id以后,肯定能够知道员工姓名,所属部门编号,部门名称和部门介绍。所以这里dept_id不是主属性,而是非主属性。但是,我们又可以发现dept_name,dept_info这两个属性也可以由dept_id这个非主属性决定,即dept_name依赖dept_id,而dept_id依赖emp_id,这样就存在了传递依赖。而且我们可以看出传递依赖的一个明显缺点就是数据冗余非常严重。    那么如何解决传递依赖问题,其实非常简单,我们只需要将dept_name,dept_info这连个属性删除就可以了,即Employee(emp_id,emp_name,emp_age,dept_id),然后再创建一个部门表Dept(dept_id,dept_name,dept_info)。

  这样如果要搜索某一个员工的部门信息dept_info,可以通过数据库连接来实现,查询语句如下:

 这样如果要搜索某一个员工的部门信息dept_info,可以通过数据库连接来实现,查询语句如下:

  注意点:

  ①数据库连接会带来一部分的性能损失

  ②并不是数据库范式越高越高

  ③有时会在数据冗余与范式之间做出权衡,在实际的数据库开发过程中,往往会允许一部分的数据冗余来减少数据库连接。

  小编结语:

  三大范式只是一般设计数据库的基本理念,可以建立冗余较小、结构合理的数据库。如果有特殊情况,当然要特殊对待,数据库设计最重要的是看需求跟性能,需求>性能>表结构。所以不能一味的去追求范式建立数据库。

  更多内容尽在课课家教育!

赞(16)
踩(0)
分享到:
华为认证网络工程师 HCIE直播课视频教程