数据库一二三BC范式详解

1.范式说明

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

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

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

举例1:

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

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

  第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被唯一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。例如员工信息表中加上了员工编号(emp_id)列,因为每个员工的员工编号是唯一的,因此每个员工可以被唯一区分。这个唯一属性列被称为主关键字或主键、主码。

  第二范式(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)。这样就符合第二范式了。

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

  满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息

举例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)。这样如果要搜索某一个员工的部门信息dept_info,可以通过数据库连接来实现,查询语句如下:

select e.emp_id,e.emp_name,d.dept_name from Employee e,Dept d where e.dept_id=d.dept_id

BC范式

  设 关系模式 R∈1NF,如果对于R的每个函数依赖X→Y,若Y不属于X,则X必含有候选码,那么R∈BCNF。
  解释一下:对于关系模式R,若 R中的所有非平凡的、完全的函数依赖的决定因素是码,则R属于BCNF。
  若R∈BCNF
  每一个决定属性集(因素)都包含(候选)码
  R中的所有属性(主,非主属性)都完全函数依赖于码
  R∈3NF(证明)
  若R∈3NF 则 R不一定∈BCNF
  在关系模式STJ(S,T,J)中,S表示学生,T表示教师,J表示课程。
  每一教师只教一门课。每门课由一名教师教,某一学生选定某门课,就确定了一个固定的教师。某个学生选修某个教师的课就确定了所选课的名称 : (S,J)→T,(S,T)→J,T→J
  由关系模式的定义可以得到如下结论,若R属于BCNF,则R有:
  1.所有非主属性对每一个码都是完全函数依赖。
  2.所有的主属性对每一个不包含它的码,也是完全函数依赖。
  3.没有任何属性完全函数依赖于非码的任何一组属性。
  由于R∈BCNF,按定义排除了任何属性对码的传递依赖与部分依赖,所以R∈3NF。但是若R∈3NF,则R未必属于BCNF。
1.第一范式:数据库的字段是单一属性,不可再分。
 解释:
  • 不能是复合属性,如果存在,应该拆分为多个属性
  • 不能是多值属性,如果存在,应该建立一个实体,而让此属性与其存在1对多的关系)
  • 不能是重复属性
2.第二范式:任何非关键字段不能部分依赖任一侯选关键字(即必须完全依赖)
 解释:
  • 表中必须存在侯选关键字,即每一行不同于其他任一行,是惟一区分的
  • 任何非关键字段不能依赖于侯选关键字的一部分
3.第三范式:任何非关键字段不能传递依赖任一侯选关键字
 解释:
  • 非关键字字段必须直接依赖任一侯选关键字
  • 非关键字段C不能依赖非侯选关键字B,因为样会形成传递依赖:侯选关键字A=>B=>C,因为这时的B往往是外键,即其他表的主键,也就是说表中不能含有其他表的非主属性
4.BC范式:任何字段都不能传递依赖任一侯选关键字
解释:
  • 与第三范式相比,一个是“任何非关键字段不能”,一个是“任何字段不能”,显然更严格了
  • 侯选关键字或其部分字段不能传递依赖其他的侯选关关键字
注释:
侯选关键字 :又叫侯选码,惟一标识一行数据,其真子集不能是侯选关键字,一个表可以存在多个侯选关键字,如用户表的username,userid
主关键字 :又叫主键,主码,被选中的用来区分其它行的侯选关键字,一个表只有一个主关键字
部分依赖 :(A,B)->C,D,如A->C,则C部分依赖A
传递依赖 :A->B->C,则C传递依赖A

注意点:

  1. 数据库连接会带来一部分的性能损失
  2. 并不是数据库范式越高越好
  3. 有时会在数据冗余与范式之间做出权衡,在实际的数据库开发过程中,往往会允许一部分的数据冗余来减少数据库连接。


你可能感兴趣的:(数据库)