先看一个表:
Ecode | Pcdoe | dept | hours |
E101 | P1 | D11 | 60 70 80 |
E103 | P2 | D33 | 90 100 110 |
E105 | P3 | D22 | 120 24 |
(表1)
首先我们看到hours属性下面的都是多值,这就是一个不规范化的表。
所谓的规范化就是满足数据库关系模型设计中的1NF,2NF, 3NF, BCNF, 4NF, 5NF。
通常4NF,5NF我们是用不上的,下面我们就来了解一下前面的几个范式吧!
1NF:表中的每一个单元都是单值,符合第一范式。
从表1中我们可以清楚的看到hours属性下面的值都分别是3个,这就违反了1NF的原则!我们可以这样修改表1使其满足1NF。
Ecode | Pcode | dept | hours |
E101 | P1 | D11 | 60 |
E101 | P1 | D11 | 70 |
E101 | P1 | D11 | 80 |
E103 | P2 | D33 | 90 |
E103 | P2 | D33 | 100 |
E103 | P2 | D33 | 110 |
E105 | P3 | D22 | 120 |
E105 | P3 | D22 | 24 |
2NF:表满足1NF,表中的每一行中的属性都函数依赖于整个主关键字,说明表符合2NF。
首先先介绍一下什么叫函数依赖吧!
所谓的函数依赖指的就是表中的A能够决定表中的B,且这种关系是一一对应的,就说B依赖于A即数学表达式中的A->B。
例如下表:
Ecode | Pcode | dept | hours |
E101 | P27 | SYSTEMS | 90 |
E305 | P27 | FINANCE | 10 |
E508 | P51 | ADMIN | NULL |
E101 | P51 | SYSTEMS | 101 |
E101 | P20 | SYSTEMS | 60 |
E508 | P27 | ADMIN | 72 |
而对于Pcode的 E101对应于P27,P51,P20,非一一对应的关系
所以我们可以说dept函数依赖于Ecode,其中Ecode是决定因子!
那我们现在就可以开始来判断该Project表是否符合2NF, 首先我们可以简单的看出,其符合1NF,
然后由表中我们可以得出(Ecode,Pcode)是该表的复合主关键字,于是我们就要判断dept,hours是否函数依赖于此关键字。
从表中E101->90,101,60, P27>90, 10, 72可以知道hours并不函数依赖于Ecode或Pcode,然而,对应每个(Ecode,Pcode)都有一个唯一对应的hours,
说明hours函数于整个关键字。
从表中我们可以简单的看出dept肯定函数依赖于Ecode,但对于Pcode, P27->SYSTEMS,FINANCE,ADMIN,说明dept不函数依赖于Pcode
因此,dept只是部分函数依赖于主关键字(Ecode,Pcode),说明该表并不满足2NF的条件:表中的每一行中的属性都函数依赖于整个关键字。
下面就给出将该表转换为2NF的方法:
(1)找出并移去部分函数依赖于整个关键字的属性,将其和其依赖于的属性放入一个表中。
(2)将剩余的属性分组。
应用上面的方法则可以得出下面两个表:
Ecode | dept |
E101 | SYSTEMS |
E305 | FINANCE |
E508 | ADMIN |
Ecode | Pcode | hours |
E101 | P27 | 90 |
E305 | P27 | 10 |
E508 | P51 | NULL |
E101 | P51 | 101 |
E101 | P20 | 60 |
E508 | P27 | 72 |
3NF:表必须先符合2NF,表中的非关键字属性都只函数依赖于主关键字。
例如下表:
Ecode | dept | depthead |
E101 | SYSTEMS | E901 |
E305 | FINANCE | E909 |
E402 | SALES | E906 |
E508 | ADMIN | E908 |
E607 | FINANCE | E909 |
E608 | FINANCE | E909 |
观察上表,我们可以知道该表的主关键字为Ecode, 那么该表是否符合3NF的要求呢?
根据2NF的定义,我们可以判断该表肯定符合2NF要求(每一行中的属性都函数依赖于整个关键字Ecode)
那么,我们现在运用3NF的定义来判断该表是否符合3NF的要求!
首先,非关键字属性为dept,depthead,我们知道他们必定函数依赖于Ecode(Ecode是主关键字),但是,从表中,SYSTEMS->E901,FINANCE->E909,SALES->E906,
ADMIN->E908,我们可以知道,depthead不仅函数依赖于Ecode,还函数依赖于dept,但dept并非是主关键字,因此,该表并不是3NF。
那么下面我们就运用下列方法将其转换为3NF吧!
(1)找出并移去函数依赖于非关键字属性的非关键字属性,将其与其函数依赖于的非关键字属性放入一个表中;
(2)将其余属性再分组。
运用上面的方法,我们就能得到下面的2个符合3NF的表:
Ecode | dept |
E101 | SYSTEMS |
E305 | FINANCE |
E402 | SALES |
E508 | ADMIN |
E607 | FINANCE |
E608 | FINANCE |
dept | depthead |
SYSTEMS | E901 |
FINANCE | E909 |
SALES | E906 |
ADMIN | E908 |
(1)表中有多个候选关键字
(2)表中多个关键字都是复合的
(3)表中的候选关键字都是重合的(至少有一个属性是重合的)
例如下表:
Ecode | Name | Pcode | hours |
E1 | VERONICA | P2 | 48 |
E2 | ANTHONY | P5 | 100 |
E3 | MAC | P6 | 15 |
E4 | SUSAN | P2 | 250 |
E4 | SUSAN | P5 | 75 |
E1 | VERONICA | P5 | 40 |
从上表中,我们明显的发现存在冗余,如果某个员工更改了名字,需要为表中进行一致的修改,否则将引起数据的不一致性。
那我们分析下该表是否已经规范化了呢?
首先,该表没有多值属性,符合1NF,
其次,我们需要确定该表的关键字, 惊奇的发现该表的关键字(能唯一确定表中一行的属性或复合属性),并不止一个,并且他们都是复合的,分别是
(Ecode,Pcode)(Name,Pcode),这时我们称他们为候选关键字。
然后再观察该表,我们可以发现,剩余的属性hours都依赖于候选关键字(Ecode,Pcode)和(Name,Pcode),因此根据2NF,3NF的定义,我们可以判定
其符合2NF,3NF。
虽然该表符合了3NF,但是,该表确实满足了3NF所不能规范化的3个条件,所以此时,我们需要采用另一种范式来规范化此表,
那就是BCNF。
BCNF:表中的每个决定因子都只能是主关键字。
又上表中我们能得到下面的函数依赖:
hours函数依赖于(Ecode,Pcode)
hours函数依赖于(Name, Pcode)
Ecode函数依赖于Name
Name函数依赖于Ecode
我们发现唯一的非关键字属性都依赖于了整个候选关键字,但是Name,和Ecode却相互依赖,说明他们是决定因子,然而他们本身并不是候选关键字。
(对于BCNF来说,每个决定因子都必须是候选关键字)
那么我们怎么样将其转换成BCNF呢?
方法:
(1)找出并移去重合的复合的候选关键字,并将其与函数依赖于其的部分放入一个表中
(2)将剩余的分组放入另一个表中。
运用上面的方法,我们就能得到下面的表:
Ecode | dept | hours |
E1 | P2 | 48 |
E2 | P5 | 100 |
E3 | P6 | 15 |
E4 | P2 | 250 |
E4 | P5 | 75 |
E1 | P5 | 40 |
Ecode | Name |
E1 | VERONICA |
E2 | ANTHONY |
E3 | MAC |
E4 | SUSAN |
这样可能会带来数据的不一致和磁盘空间上的浪费,但换来的确是数据库存取数据的效率!
当应用程序需要大量频繁的访问数据库中需要连接的表,而两张表格的数据确不多的情况下,增加一定的冗余就可以换来存取上的高效率,何尝不可!