三大范式和BCNF
1NF
不满足第一范式(1NF)的数据库就不是关系数据库。(即能写成R(A,B,C,D)的都满足1NF)
第一范式是指数据库表的每一列(即每个属性)都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。
简而言之,无重复的列,每个分量都是不可分的数据项,则称满足第一范式。
例:
学号 | 姓名 | 学号 | 联系方式 |
---|---|---|---|
1233 | 张三 | 1233 | 电话:123456789,e-mail:123@163.com |
由于联系方式可以再分为电话和e-mail所以可分且学号重复,所以不满足1NF
正确:
学号 | 姓名 | 电话 | |
---|---|---|---|
1233 | 张三 | 123456789 | 123@163.com |
2NF
第二范式(2NF)要求数据库表中的每个实例或行必须可以被唯一地区分。实体的属性完全依赖于主关键字。
所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,
如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,
简而言之,在满足第一范式的情况下去除部分依赖,即非主属性必须完全依赖于主键
例:
学号 | 课程号 | 得分 | 课程名 |
---|---|---|---|
123 | 12 | 1 | 数据库 |
主关键字字即主键 学号,课程号都是主键 课程名只依赖课程号,是部份依赖所以不满足2NF
正确:
学号 | 得分 |
---|---|
123 | 1 |
课程号 | 课程名 |
---|---|
12 | 数据库 |
例:R(A,B,C,D) FD:AB->C,B->D,AB->D
由fd可知B->D,所以AB->D为部分函数依赖 不满足2NF
修改:
把BD单独列出一张表 R(A,B,C),R(B,D)
3NF
在第二范式的基础上,不存在属性依赖于非主属性,且不存在传递依赖。
简而言之,在满足第二范式的情况下,消除传递依赖
例:
学生姓名 | 课程号 | 老师 | 教师职称 | 教室 |
---|---|---|---|---|
张三 | 123 | 李四 | 讲师 | 111 |
主键为学生姓名和课程号,学生姓名和课程号决定老师,老师决定教师职称。这里出现了传递依赖,且出现了非主属性依赖非主属性
正确:
学生姓名 | 课程号 | 教室 |
---|---|---|
张三 | 123 | 111 |
老师 | 教师职称 |
---|---|
李四 | 讲师 |
例2:R(A,B,C,D,E)FD:AB->C,AB->E,C->D
通过闭包运算 知道AB为主键,所以C->D带来属性依赖非主属性,从而带来了传递依赖,所以不满足3NF
修改
把C,D单独列一张表 R(A,B,C,E),R(C,D)
BCNF
BCNF实际是第三范式的修正,必须满足三大条件:
·所有非主属性必须对每个码都完全依赖
·所有主属性必须完全依赖于所有不包含它的码
·没用任何属性依赖于非码
简而言之,fd的左边必须全是超键,主属性必须完全依赖于不包含它的超键
例:
每个管理员只管理一个仓库,一个仓库存多种物品
仓库id | 管理员 | 存货 | 物品 |
---|---|---|---|
123 | 张三 | 10 | 苹果 |
设主键为(仓库id,物品)和(管理员,物品)由仓库id和物品可以知道管理员和存货,由管理员和物品可以知道仓库id和存货,由题干知道管理员确定仓库id,仓库id也可以确定管理员。仓库id和管理员不是超键,所有不满足第三个条件,不满足BCNF
正确:
仓库id | 存货 | 物品 |
---|---|---|
123 | 10 | 苹果 |
仓库id | 管理员 |
---|---|
123 | 张三 |
例:
R(A,B,C,D) FD:AC->BD,BC->AD,A->B,B->A;
观察可见非主属性只有D,D也完全依赖于主键,满足第一条件。
通过闭包计算 主键为AC,BC,所以主属性为A,B,C。可见A,B,C都满足第二条件
因为A,B不是主键,所以A->B,B->A不满足第三条。所以不是BCNF
修改:
把AB单独列表,R(A,C,D),R(A,B)
码,键区别与联系
·码即键
·码(键/超键) 包含 候选键 包含 主键
·超键:能够唯一标识一条记录的属性或属性集
·候选键能够唯一标识一条记录的最小属性集。即超键=候选键+其它属性
例:
在R(A,B,C)中,A、B为候选键,AC为超键
·主键:在候选键中选一个。
例:
在候选键A,B中选取A为主键
·主属性:组成候选键的所有属性
例:
在R(A,B,C)中,主属性为A,B
·外键:在子表出现的主表的主键,成为子数据表的外键
例:
在R(A,B,C),T(A,D)中,A为R的主键,D为T的主键,A为T的外键
求闭包
在R<U,E>中 属性集S包含于U,S通过自身的属性在E中通过推导得到的所有属性集合。
即{S}的闭包,记为{S}+。
例:
R(A,B,C,D) FD:DC->B,C->D;求AC的闭包
我们已知AC两个属性,在FD中寻找右边{A,C}的子集,发现C->D,则 把D添加到AC的闭包中。
此时{AC}+={A,C,D},可以看到DC->B,所以把B也添加到闭包中。
得{AC}+={A,B,C,D}
求候选键
候选键即所求的闭包等于U。如上题,AC即为候选键。
判断分解为无损链接(chase检验)
先通过分解后的候选键和R中的属性列出关系表
先观察表,找没有下标的相同列A
再在FD 查找是否存在A->x(x属于R中的属性)
如果存在,把相同A列所在行的x列用最小的下标替换
重复上述步骤,直到无法再用更小的下标替换或者出现一行全是无下标的
注:函数依赖可以重复使用
例:
设有 R( U , V , W , X , Y , Z ),FD:F = { U→V , W→Z , Y→U , WY→X },现有下列分解:
1.ρ1 ={ WZ , VY , WXY , UV }
2.ρ2 = { UVY , WXYZ }
判断是否为无损连接
1.
分解后的候选键 | U | V | W | X | Y | Z |
---|---|---|---|---|---|---|
WZ | u1 | v1 | w | x1 | y1 | z |
VY | u2 | v | w2 | x2 | y | z2 |
WXY | u3 | v3 | w | x | y | z3 |
UV | u | v | w4 | x4 | y4 | z4 |
把分解后的主属性所在每行中用原字母代替,其它属性加上下标。
观察FD,可以看到U->V,在U列查找相同字母所在的行,再查看对应行所在的V列,在v列用最小的下标代替其它。
可以发现U->V,没有满足条件的行
再使用W->Z
分解后的候选键 | U | V | W | X | Y | Z |
---|---|---|---|---|---|---|
WZ | u1 | v1 | w | x1 | y1 | z |
VY | u2 | v | w2 | x2 | y | z2 |
WXY | u3 | v3 | w | x | y | z |
UV | u | v | w4 | x4 | y4 | z4 |
同理,再使用Y->U
分解后的候选键 | U | V | W | X | Y | Z |
---|---|---|---|---|---|---|
WZ | u1 | v1 | w | x1 | y1 | z |
VY | u2 | v | w2 | x2 | y | z2 |
WXY | u2 | v3 | w | x | y | z |
UV | u | v | w4 | x4 | y4 | z4 |
同理,再使用WY->X
分解后的候选键 | U | V | W | X | Y | Z |
---|---|---|---|---|---|---|
WZ | u1 | v1 | w | x1 | y1 | z |
VY | u2 | v | w2 | x2 | y | z2 |
WXY | u2 | v3 | w | x | y | z |
UV | u | v | w4 | x4 | y4 | z4 |
没有满足条件的
观察每一行 发现没有一行是全部没有下标的,即该分解不是无损分解。
2.初始化表
分解后的候选键 | U | V | W | X | Y | Z |
---|---|---|---|---|---|---|
UVY | u | v | w1 | x1 | y | z1 |
WXYZ | u2 | v2 | w | x | y | z |
使用U->V 没有满足条件的
使用W->Z 没有满足条件的
使用Y->U 有相同Y,用最小的u替换U
分解后的候选键 | U | V | W | X | Y | Z |
---|---|---|---|---|---|---|
UVY | u | v | w1 | x1 | y | z1 |
WXYZ | u | v2 | w | x | y | z |
使用WY->X 没有满足条件的
再使用U-V 有相同u,替换v
分解后的候选键 | U | V | W | X | Y | Z |
---|---|---|---|---|---|---|
UVY | u | v | w1 | x1 | y | z1 |
WXYZ | u | v | w | x | y | z |
观察发现出现一行都没有下标,则为无损连接。
求最小依赖集
步骤:
1.先把FD的右边分解到只含有一个属性
2.对每个FD的左边求闭包不包含(所求的函数依赖),如果不包含右边,则保留,否则去掉
3.在第二部的前提下,对左边包含不止一个属性,对其真子集求闭包,如果子集的闭包包含右边,则用子集替换。
例:
关系模式R<U,F>,U={A,B,C,D,E},F={A→BC,ABD→CE,E→D}
1.F={A->B,A->C,ABD->C,ABD->E,E->D}
2{A}+={A,C},{A}+={A,B},{ABD}+={A,B,C,D,E}(含有C);{ABD}+={A,B,C,D},{E}+={E};
所以FD:{A->B,A->C,ABD->E,E->D};
3.{AB}+={A,B,C},{AD}+={A,B,C,D,E}(包含右部);{BD}+={B,D};{B}+={B};{A}+={A,B,C};{D}+={D};
所以最小依赖集为{A->B,A->C,AD->E,E->D}
注:第三步求子集闭包时,FD是包含ABD->E的;
函数依赖集的投影
1.对关系模式R的FD进行推断,把所有的依赖集记为G
2.对投影的关系模式R1的真子集X 在原FD中求闭包,把闭包中属于R1的属性集记为A.
3.在G中查找满足X->A的函数FD添加到R1的FD中,记为F
4.对F求最小依赖集
例:R(A,B,C,D) FD: A->B,B->C,C->D 投影获得R1(A,C,D) 求R1的FD
1.对R的FD进行推断 FD:
A->B,A->C,A->D,B->C,B->D,C->D,AC->B,AB->C,AB->D,AC->D;
2.求真子集闭包
{A}+:{A,B,C,D} A为候选键,所以A的超集不用再求闭包
{C}+:{C,D}
{D}+:{D}
{CD}+:{C,D}
3.在{A}+中查询满足X->A(因为B不在R1中,所有要把B删除)的依赖
A->C,A->D,AC->D;
同理 对余下进行查询
{C}+ FD:C->D
{D}+ FD:无
{CD}+ FD:C->D
所以R1的FD为A->C,A->D,AC->D,C->D;
4.对R1的FD求最小依赖集
得到最后结果
R1(A,C,D) FD:A->C,A->D,C->D
模式分解
分解为3NF
1.通过闭包运算,求得候选键
2.求出最小依赖集
3.根据左部相同的并为一组规则,对依赖集分组
4.查看分的小组是否包含候选键,包含则为无损连接且保持函数依赖,否则添加一个候选键分组
例:
R(A,B,C,D,E) ,FD:{AB->C,C->B,D->E,D->C} 若R不是3NF,将R分解为无损且保持函数依赖的3NF。
第一步:
求得码是AD
第二步:
FD:{AB->C,C->B,D->E,D->C}
第三步:
u1=ABC,u2=CB,u3=DCE
第四步:
u1=ABC,u2=CB,u3=DCE,u4=AD
得:
R1({A,B,C},{AB->C,C->B}),
R2({D,E},{D->E,D->C}),
R3({A,D},{∅})
分解为BCNF
1.检查R(U,F)是否存在违例,如果否进行第二步
2.求得候选键
2.假设为X->Y违例,计算{X}+,使R1={X}+,R2=U+X-{X}+;
3.求得R1,R2的FD
4.判断R1,R2是否违例
首先明确什么是违例。即违背满足BCNF范式的四个条件,只要不满足即违例。然后通过上述布步骤,进行递归,知道所以关系模式都符合BCNF
例:
R(A,B,C,D,E,F,G,H) FD:A→BCG,G→H,D→EF 分解为符合BCNF的关系模式
1.求得关系模式的候选码为AD
2.可见D->EF不满足任何属性都依赖与码 存在违例
3.对D求闭包,{D}+={DEF},则R1={DEF},R2={ABCDGH};
4.R1(D,E,F) FD:D->EF
R2(A,B,C,D,G,H) FD:A->BCG,G->H
5可见R1满足了BCNF,R2不满足
进行递归
1.R2的候选键为A
2.G->H不满足BCNF的条件
3.对G求闭包 {G}+={GH},R3={ABCDG};
4.R2(G,H) FD:G->H
R3(A,B,C,D,G) FD:A->BCG
5.R2,R3都满足BCNF条件
综上,最终分解为 R1(D,E,F) FD:D->EF,R2(G,H) FD:G->H,R3(A,B,C,D,G) FD:A->BCG