码迷,mamicode.com
首页 > 其他好文 > 详细

解析范式(1NF-4NF)

时间:2017-10-17 15:06:14      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:col   模式   aaa   复合   表数   strong   定义   上海   ext   

一、1NF

1.1 1NF的定义:

  关系数据库中的关系是要满足一定要求的,满足不同程度要求的为不同的范式。满足最低要求是第一范式(1NF),1NF的定义如下:

    1NF:关系中的每一个分量必须是一个不可分的数据项。

  通俗地说,第一范式就是表中不允许有小表的存在。比如,对于如下的员工表,就不属于第一范式:

员工表

员工编号

员工姓名

出生日期

薪资/月

所属部门

基本工资/月

补贴/月

1

Tom

19900908

9000

1000

101

...

...

...

...

...

 

  上表中,出现了属性薪资又被分为基本工资和补贴两个子属性,就好像表中有分割了一个小表,这就不属于第一范式。如果将基本工资和补贴合并,那么该表符合1NF。

 

1.2 1NF存在的问题;

  1NF是最低一级的范式,范式程度不高,存在很多的问题。比如用一个单一的关系模式学生来描述学校的教务系统:

  学生(学号,学生姓名,所在系,系主任姓名,课程号,成绩)

学生表

学号

学生姓名

所在系

系主任姓名

课程号

成绩

201102

ABB

计算机系

章三

04

70

201103

AAA

计算机系

章三

05

60

201103

AAA

计算机系

章三

04

80

201103

AAA

计算机系

章三

06

87

201104

ABC

机械系

王五

09

79

...

...

...

...

...

...

 

  假如选定学号为主键,这个表满足第一范式,但是存在如下问题:

  ·数据冗余:

    一个系有很多的学生,同一个系的学生的系主任是相同的,所以系主任名会重复出现。

  ·更新复杂:

    当一个系换了一个系主任后,对应的这个表必须修改与该系学生有关的每个元组。

  ·插入异常:

    如果一个系刚成立,没有任何学生,那么这个无法把这个系的信息插入表中。

  ·删除异常:

    如果一个系的学生都毕业了,那么在删除该系学生信息时,这个系的信息也丢了。

 

二、2NF

2.1 2NF的定义:

  2NF的定义如下:

    如果关系R属于1NF,且每一个非主属性完全函数依赖于任何一个候选码,则R属于2NF。

  通俗地说,2NF就是在1NF的基础上,表中的每一个非主属性不会依赖复合主键中的某一个列。

  按照定义,上面的学生表就不满足2NF,因为学号不能完全确定课程号和成绩(每个学生可以选多门课)。将学生表分解为:学生(学号,学生姓名,系编号),系(系编号,系名,系主任),选课(学号,课程号,成绩)。每张表均属于2NF。

  新定义一张表:销售表(产品id,地区id,价格,产品名),同一个产品在不同地区价格不同。这个表就不属于2NF,因为非主属性产品名不是完全函数依赖于主键,而是完全依赖于产品id,即表中存在非主属性对主键的部分依赖。将销售表分解:产品(产品id,产品名),销售表(产品id,地区id,价格)。每张表均属于2NF。

 

2.2 2NF存在的问题:

  下面举例说明2NF存在的相应问题。

  对于公司里的员工管理,每个员工只能属于一个部门,每个部门可以有多个员工,定义如下关系模式:

  员工管理表(员工id,员工名,所属部门id,部门经理);

  对应的表:

员工id

员工名

所属部门

部门经理

001

Tom

销售部

张三

002

Marry

销售部

张三

003

Mike

研发部

李四

...

...

...

...

  存在的问题:

  1、删除异常:

    如果某个部门的人都跳槽了,那么在删除这些员工的同时也丢失了这个部门的信息。

  2、修改复杂:

    如果一个员工换了一个部门,不但要修改所属部门,还要修改部门经理这个属性列。

  3、插入异常:

    如果公司新成立了一个部门,但是目前没有招收员工,那么这个部门信息也无法插入到这个表中,因为没有主键。

 

三、3NF

3.1 3NF的定义:

  3NF的定义:在满足1NF的基础上,表中不存在非主属性对码的传递依赖。也就是说表中非主属性不会间接地依赖于码。

  如上面的员工管理表就不属于3NF,因为非主属性部门经理依赖于所属部门,所属部门依赖于员工id,即部门经理传递依赖于员工id。将员工管理表分解:员工管理(员工id,员工名,部门名),部门(部门名,部门经理)。则每张表均属于3NF。

 

3.2 3NF存在的问题:

  现在有这样的一个场景:对于一个工程(ENO)的实施,每个工程需要多个零件,每个供应商(SNO)只生产一个零件(PNO)且受工厂规模所限只能同时供应一个工程,每个工程使用的同一个零件都来自同一个生产商。

  定义关系模式:SPE(SNO,PNO,ENO)。

SPE表

SNO

PNO

ENO

上海齿轮加工厂

齿轮

造船工程

上海螺母加工厂

螺母

造船工程

鞍山钢床加工厂

钢床

造船工程

天津齿轮加工厂

齿轮

机车制造工程

天津螺母加工厂

螺母

机车制造工程

...

...

...

  上表中存在如下函数依赖:

    (ENO,PNO)→SNO

    (ENO,SNO)→PNO

    SNO→PNO

  SPE是属于3NF的,因为根据定义,表中不存在非主属性对码的传递依赖和部分依赖。但是这张表存在如下的问题:

  1、插入异常:

    如果有一个新的工厂建立了,但是这家工厂还没有接到任何订单,那么无法将这个工厂信息插入到SPE中,因为缺少了主属性ENO。

  2、删除异常:

    如果某个供应商只给一个工程提供零件,现在这个工程不再需要这个零件了。那么PNO就要删除,而PNO是主属性,整个元组都被删除了,这样就丢失了一个供应商信息。

 

四、BCNF

4.1 BCNF的定义:

  BCNF比3NF更进一步,可以认为是扩充的3NF,其定义如下:

    在第一范式的基础上,若关系R中的每一个决定因素都必含有码,则关系R属于BCNF。

  很显然,上面的SPE表不属于BCNF,因为SPE中存在一个决定因素SNO,SNO不含有码。将SPE表分解:SP(SNO,PNO),SE(SNO,ENO)。则每张表均属于BCNF。

 

4.2 BCNF存在的问题:

  仍以上面的工程实施场景为例:假设每个供应商可以生产多个零件,可以供应给多个工程,一个工程需要多个零件,但同一个工程的同一个零件必须来自同一个供应商。

  那么关系SPE(SNO,PNO,ENO)对应的表数据可能是如下:

SPE表

SNO

PNO

ENO

S1

P1

E1

S1

P1

E2

S1

P1

E3

S1

P2

E1

S1

P2

E2

S1

P2

E3

S2

P5

E4

S2

P5

E5

S2

P7

E4

...

...

...

  此时表SPE存在如下的函数依赖:

    (PNO,ENO)→SNO

  根据BCNF的定义,此时表SPE属于BCNF。但是这样的关系模式仍具有不好的地方:数据冗余度太大。假如供应商S3生产了n个零件,每个零件供应给m个工程,那么显然S3要在表中重复m*n次。

 

五、4NF

5.1 4NF的定义:

  关系模式R属于1NF,对于R中的每一个非平凡多值依赖X→→Y,X都含有码,则R属于4NF。

  通俗地说,对于有三个属性的表,给定属性A一个值,剩余两个列之间不存在多对多的关系。例如,在上面的SPE表中,给定SNO=S1,PNO和ENO之间很明显存在多对多的关系,故上表是不属于4NF的。

  根据4NF的定义可知,4NF所允许的非平凡的多值依赖实际上就是函数依赖,4NF就是消除表中的非平凡多值依赖关系。

 

5.2 4NF存在的问题:

  一般地,4NF属于规范程度比较高的范式了。但是考虑到连接依赖的话,4NF中也仍存在数据冗余,插入、修改、删除异常等问题。如果消除了4NF中的连接依赖,则达到了5NF的关系模式。

 

六、对范式的学习总结:

  如果只考虑函数依赖,那么BCNF范式最彻底,已消除插入和删除的异常。对比3NF,其不彻底性表现在表中可能存在主属性对码的部分依赖和传递依赖。

  如果考虑到多值依赖,那么4NF范式是规范程度最高的。但4NF中可能存在连接依赖的关系,而5NF可以消除连接依赖。

  在数据库中,有时并不是规范化程度越高越好。因为范式越高,产生的表就越多,一个简单的查询就可能涉及到多张表的关联。一般地,数据库中的表都在3NF。

 

 

解析范式(1NF-4NF)

标签:col   模式   aaa   复合   表数   strong   定义   上海   ext   

原文地址:http://www.cnblogs.com/jiang-jt/p/7680625.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!