简介
依赖(dependency)理论涉及如何构建一个良好的关系数据库模式,以及当一个模式存在缺陷时应如何改 进 。
函数依赖
关系R上的函数依赖(functional dependency,FD)是指如果R的两个元组在属性上一致,那么它们必定在其他属性上也一致。该函数依赖形式地标记为,并称函数决定。如果确定关系R的每个实例都能使一个给定的FD为真,那么称R满足函数依赖f。这是在R上声明来一个约束,而不是仅仅针对R的一个特殊实例。
函数依赖中的函数是什么意思呢?被称为“函数”依赖是因为在这条规则中,有一个函数对于一个值的列表(列表中每个值对应中的一个属性),都产生一个唯一的B值。这个函数和数学中常见的函数不同,因为这条规则无法用来计算。也就是说,不能根据前面的属性集算出后面的属性,它只有通过关系的观察才能得出结果。
分解规则:可以用一个FD的集合(i=1,2,...m)替换FD
组合规则:可以用一个FD替换FD集合(i=1,2,...m)
平凡函数依赖:如果关系上的一个约束对所有关系实例都成立,且与其他约束无关,则称其为平凡FD。平凡FD是这样一类FD:,其中
平凡依赖规则:FD 等价于, 其中C是集合B中而不是集合A中的属性
传递规则:若关系R中FD和都成立,那么FD在R中也成立
关系的键
如果下列条件满足,就认为一个或多个属性集{}是关系R的键。
1 这些属性函数决定关系的其他所有属性。也可以说,关系R不可能存在两个不同的元组,它们具有相同的值
2 在{}的真子集中,没有一个能函数决定R的所有其他属性。也就是说,键必须是最小的
超键
一个包含键的属性集就叫做超键,超键都满足键的第一个条件,但不符合第二个。
属性的闭包
假设是属性集合,S是FD的集合,则S集合下的属性集合的闭包是满足下面条件的属性集合B,即使得每一个满足S中所有FD的关系,也同样满足,属性集合的闭包记为
计算属性集合闭包的算法
输入:属性集合,FD的集合S
输出:
1 如果有必要,分解S中FD,使每个FD的右边只有一个属性
2 设X是属性集合,也就是闭包,首先将X初始化为
3 反复寻找这样的FD:,使得在X中,而C不在X中;若找到,则把C加入X,并重复这个过程。因为集合X只能增长,而任何一个关系模式中的属性都是有限的,所有最终没有任何元素能再加入X时,本步骤结束
4 当不能再看见任何属性时,集合X就是
计算闭包能方便的对某些函数依赖是否存在做出判断,举个例子,假如相对于FD集合S,,我们可以轻易的判断FD可以推导出,但不能推导出
闭包和键
注意当且仅当是关系的超键时,才是这个关系的所有属性的集合。只有这样,才能函数决定所有其他的属性。如果要验证是否是一个关系的键,可以先检查是否包含了该关系的全部属性,然后再检查不存在从中移除一个属性后的集合X,使得包含关系的所有属性。
函数依赖的闭包集合
给定一个FD集合S,则任何与S等价的FD集合都被称为S的基本集(basis)。为避免基本集的激增,只考虑那些FD的右边是单一属性的基本集,满足下面三个条件的基本集B被称为关系的最小化基本集(minimal basis),注意,最小化基本集不一定是唯一的。
1 B中所有FD的右边均为单一属性
2 从B中删除任何一个FD后,该集合不再是基本集
3 对于B中的任何一个FD,如果从其左边删除一个或多个属性,B将不再是基本集
投影函数依赖
假设有一个含有FD集合S的关系R,通过计算得到L对其部分属性的投影,那么中有哪些FD成立?这个问题的答案原则上可以通过计算函数依赖集S的投影(projection of functional dependencies S)获得。S的投影是所有满足下面条件的FD的集合:
1 从S推断而来 2 只包含的属性
函数依赖集的投影算法
输入:关系R和通过计算得到的关系,以及在R中成立的FD的集合S
输出:在中成立的FD集合
方法:1 另T为最终输出FD的集合,初始化T为空集
2 对于的属性集合的每一个子集X,计算,该计算根据FD集合S,可能会涉及一些在R模式中却不在模式中的属性。对于所有在中且属于的属性A,将所有非平凡的FD 添加到T中
3 现在,T是在中成立的FD基本集,但可能不是最小化基本集。通过如下方法对T进行修改来构造最小化基本集。
a 如果T中的某个FD F能从T中其他FD推断出来,则从T中删除F
b 设是T中的一个FD,Y至少有两个属性,从Y中删除一个属性并记为Z。如果能从T中的FD(包含)推断,则使用替换
c 重复以上两个步骤,直到T不再变化
关系数据库模式设计
如何设计一个好的关系模式呢,一般来说,我们首先设计好一个能工作的关系模式,然后分析这个模式存在哪些问题,然后对已有模式进行分解,使得分解后的关系符合BCNF范式,同时也会消除之前设计的问题。
当试图在一个关系中包含过多信息时,产生的问题(如冗余)称为异常,异常基本类型有:
冗余:信息在多个元组重复
更新异常:更新某字段时,可能更新来部分元组中的字段,但另外一些元组的字段忘记更新
删除异常:某些不太相关的属性在一个关系表中,如果某属性需要清空,结果会导致另外的属性也被一起删掉,这可能不是用户所希望看到的
分解关系
一般用分解关系的方法来消除异常,给定一个关系,把它分解为关系和,并且满足:
1
2
3
Boyce-Codd范式
分解的目的就是将一个关系用多个不存在异常的关系替换。也就是说,在一个简单的条件下保证讨论的异常不存在,这个条件成为Boyce-Codd范式,简称BCNF。关系R属于BCNF当且仅当:如果R中非平凡FD 成立,则是关系R的超键。
任意一个两元关系属于BCNF,我们可以设想两个属性A和B,分别看下可能出现的情形:
1 没有非平凡的FD。因为只有非平凡的FD才能违反这个条件,所以BCNF肯定成立,此时{A,B}是唯一的键
2 成立,但不成立,这种情况下,A是唯一的键,每个非平凡的FD左边都包含A,因此没有违反BCNF
3 成立但不成立,同上
4 和都成立,此时A和B都是键,由于任一FD的左边至少会包含A和B中的一个,因此,没有FD违反BCNF
BCNF分解算法如下
输入:关系和其上的函数依赖集
输出:由分解出的关系集合,其中每个关系均属于BCNF
方法:下列步骤可以被递归地用于任意关系R和FD集合S。初始时,R = ,S=
1 检验R是否属于BCNF。如果是,不需要做任何事,返回{R}作为结果
2 如果存在BCNF违例,假设为。首先计算X的闭包。选择作为一个关系模式,并使另一个关系模式包含属性X以及那些不在中的属性
3 计算和的FD集,分别记为和
4使用本算法递归的分解和。返回这些分解得到的结果集合。
分解的优劣
一个关系模式被分解为一系列属于BCNF的关系前,它可能包含异常,分解之后则不包含异常。这就是所谓的“优”。但是分解也可能造成一些坏的结果。本节介绍一个分解具有的三个性质。
1 消除异常(Elimination of Anomalie)
2 信息的可恢复(recoverability of Information)。是否能够从分解后的各个元组中恢复原始关系
3 依赖的保持(Preservation of Dependencies)。如果FD的投影在分解后的关系上成立,能否确保对分解后的关系用连接重构获取的原始关系仍然满足原来的FD
BCNF分解可以保证1 和 2,第三范式能保证2和3,但没有方法能同时保证这三个性质。
如果在关系R上成立,且R的属性集为,则
第三范式
关系R属于第三范式,如果它满足:只要是非平凡FD,那么或者是超键,或者每个属于但不属于A的属性都是某个键的成员
具有无损连接和依赖保持性的3NF关系综合算法
输入:关系R和其上成立的函数依赖集F
输出:由R分解出的关系集合,其中每个关系均属于3NF。分解具有无损连接和依赖保持性质
方法:1 找出F的一个最小基本集,记为G
2 对于G中的每一个FD ,将XA作为分解出的某个关系的模式
3 如果第2步中分解出的关系的模式均不包含R的超键,则增加一个关系,其模式为R的任何一个键
多值依赖(multivalued dependency,简称MVD)
多值依赖是指在关系R中,当给定某个属性集合的值时,存在另外一组属性集合,该组属性的值与关系中所有其他属性的值独立。准确的说,若给定R中属于集合A的各属性的值,存在一个属性集B,其中属性的值独立于R中既不属于A也不属于B的属性集合的值,则称MVD
准确的说,若要MVD成立,则对于R中每个在所有A属性上一致的元组对t和u,能在R中找到满足下列条件的元组v:
1 在A属性上的取值与t和u相同
2 在B属性上的取值与t相同
3 在R中不属于A和B的所有其他属性上的取值与u相同
MVD规则
平凡MVD规则,如果,则MVD在任何关系中成立
传递规则,如果关系中存在和,则
升级规则,每个FD都是MVD。
第四范式
如果对于R中的每个非平凡MVD,都是超键,则R属于第四范式
分解为第四范式
输入:关系,其上的FD和MVD集合为
输出:由分解出的关系集合,其中每个关系均属于4NF,分解具有无损连接性质
方法:一次执行下列步骤,另,
1在R中找到一个4NF违例,记为,其中不是超键。注意这个MVD可以是S中的一个真的MVD,也可以源自S中对应的FD,这是因为每个FD都是MVD。如果不存在,返回,R自身就是一个合适的分解
2如果存在这样的4NF违例,则将含有该4NF违例的关系R分解为两个模式
a ,其模式为A和B
b ,其模式是A以及R中所有不属于A和B的其他属性
3 找出在和上成立的FD和MVD。根据投影后的依赖关系递归地分解和
注意,4NF蕴含BCNF,BCNF蕴含3NF,如下图所示