关系数据库设计

码和函数依赖:

令r(R)是一个关系模式。R的子集K是r(R)的超码的条件是:在r(R)中的合法实例中,对于r的实例中的所有元组t1, t2总满足:若t1≠t2则,t1[K]≠t2[K]。也就是说,在关系r(R)中没有两条元组在属性集K上可能具有相同的值。

考虑关系模式r(R),令a是R的子集,且b是R的子集。

给定r(R)的一个实例,称这个实例满足函数依赖a→b的条件是:对实例中所有元组t1和t2,若t1[a]=t2[a],则t1[b]=t2[b]。

如果在r(R)的每个合法实例中都满足函数依赖a→b,则称函数依赖a→b在关系模式r(R)上是成立的。

有些函数依赖称为平凡的,因为它们在所有关系中都满足。一般地,如果b是a的子集,则形如a→b的函数依赖是平凡的。

函数依赖理论:

给定关系模式r(R)上的函数依赖集F,如果r(R)的每一个满足F的实例也满足 f ,则R上的函数依赖 f 被 r 上的函数依赖集F逻辑蕴含。

Armstrong公理:

  1. 自反律,若a为一属性集且b是a的子集,则a→b成立。
  2. 增补律,若a→b成立且c为一属性集,则ac→bc成立。
  3. 传递律,若a→b和b→c成立,则a→c成立。

简化Armstrong公理:

  1. 合并律,若a→b和a→c成立,则a→bc成立。
  2. 分解律,若a→bc成立,则a→b和a→c成立。
  3. 伪传递律,若a→b成立和bc→d成立,则ac→d成立。

 F的闭包是被F逻辑蕴含的所有函数依赖的集合,记作F+

F的闭包F+:

给定一个关系R的函数依赖集F,则F的闭包F+的算法过程如下:

F+=F
repeat
  for each F+中的函数依赖 f
    在f上应用增补律和自反律
    将结果放到F+中
  for each F+中的一对函数依赖f1和f2
    如果f1和f2能用传递律结合起来
    则将结果放到F+中
until F+不再发生变化

属性a的闭包a+

如果a→b,则称b为属性a函数确定。

令a为一个属性集。则将函数依赖集F下被a函数确定的所有属性的集合称为F下a的闭包,记作a+。计算F下a的闭包a+的算法过程如下:

result=a
repeat
  for each 函数依赖 b→c in F do
    begin
      if b 属于result then result=result∪c
    end
until(result不变)

如何获取R的所有候选码?

对于一个关系R,对其属性集合进行任意组合,然后依次计算这些属性组合的闭包。如果某个属性组合的闭包包含所有属性,那么这个属性组合就是候选码。

属性闭包算法的多种用途:

  1. 为了判断a是否为超码,我们计算a+,检查a+是否包含R中的所有属性。
  2. 通过检查b是否的a+的子集,可以检查出函数依赖a→b是否成立。
  3. 另一种计算F的闭包F+的方法:对任意的a,a是R的子集,可以找出闭包a+,对任意的b,b是a+的子集,可以输出一个函数依赖a→b。

如果去除函数依赖中的一个属性不改变该函数依赖集的闭包,则称该属性是无关的。

无关属性的形式化定义如下:考虑函数依赖集F及F中的函数依赖a→b,

  • 如果A是a的一个元素并且F逻辑蕴含(F - {a→b})∪{(a-A)→b},则属性A在a中是无关的。
  • 如果A是b的一个元素并且函数依赖集(F-{a→b})∪{a→(b-A)}逻辑蕴含F,则属性A在b中是无关的。

无损分解:将关系模式R分解为R1和R2,如果R1∩R2是R1或R2的超码,则R上的分解就是无损的。

Boyce-Codd范式:

具有函数依赖集F的关系模式R属于BCNF的条件是,对F+中的所有形如a→b的函数依赖(其中a是R的子集,并且b是R的子集),下面至少有一项成立:

  1. a→b是平凡的函数依赖(即,b是a的子集)
  2. a是模式R的一个超码

一个数据库设计属于BCNF的条件是,构成该设计的关系模式集中的每个模式都属于BCNF。

设R为不属于BCNF的一个模式。则存在至少一个非平凡的函数依赖a→b,其中a不是R的超码。则需要在设计中用以下两个模式取代R:

  • a∪b
  • R - ( b - a ) 

判定方法(避免计算F+是因为F+一般都很大):

在某些情况下,判定一个关系是否属于BCNF可简化成:

  • 为了检查非平凡的函数依赖a→b是否违反BCNF,计算a+,并且验证它是否包含R中所有属性,即验证它是否是R的超码。
  • 检查关系模式R是否属于BCNF,仅需检查给定集合F中的函数依赖是否违反了BCNF就足够了,不用检查F+中的所有函数依赖。

需要注意的是,如果一个关系没有被分解,那么我们可以证明如果F中没有函数依赖违反BCNF,那么F+中也不会有函数依赖违反BCNF。但是当一个关系分解后,这个结论将不再成立。

所以为了检查R分解后的关系Ri是否属于BCNF,可以用如下判定:

  • 对于Ri中属性的每个子集a,确保a+要么不包含Ri-a的任何属性,要么包含Ri的所有属性。

如果Ri上有某个属性集a违反了该条件,考虑如下的函数依赖,可以证明它出现在F+中:

         a→(a+-a)∩Ri

分解方法:

给出一个关系模式R,若R不属于BCNF,则可用下面的算法将R分解成一组BCNF模式R1,R2,...,Rn

result:={R};
done:=false;
计算F+while (not done) do
if(result中存在模式Ri不属于BCNF)
then begin
    令 a→b 为一个在Ri上成立的非平凡函数依赖,满足 a→Ri 不属于F+,并且a∩b;
    result:=(result-Ri)∪(Ri-b)∪(a,b)
end
else
done:=true;

下面给出一个例子:

给定关系模式class(class_id, title, dept_name, creadits, sec_id, semester, year, building, room_number, capacity, time_slot_id)

给出函数依赖(a→a+的形式):

course_id→title, dept_name, credits

building, room_number→capacity

course_id, sec_id, semester, year→building, room, time_slot_id

易知,该模式的候选码为{course_id, sec_id, semester, year}。

  • 分解class:

函数依赖course_id→title, dept_name, credits成立,但course_id不是超码。因此class不属于BCNF。所以将class替换成:

course(course_id, title, dept_name, credits)

course-1(course_id, sec_id, semester, year, building, room_number, capacity, time_slot_id)

course上唯一成立的非平凡函数依赖:course_id→title, dept_name, credits,因为course_id是course的超码,所以course属于BCNF。

  • 分解class-1

函数依赖building, room_number→capacity在class上成立,但{building, room_number}不是class-1的超码,所以将class-1替换成:

classroom(building, room_number, capacity)

section(course_id, sec_id, semester, year, building, room_number, time_slot_id)

显而易见,classroom和section属于BCNF

需要注意的一点是,如果一个关系已经被分离过了,那么在原有的函数依赖集合F中找不到使该关系不满足BCNF的函数依赖并不意味着这个关系就是函数依赖,而应该遍历函数依赖集合的闭包F+,来寻找相关的函数依赖。

posted @ 2019-04-29 11:17  Hang3  阅读(288)  评论(0编辑  收藏  举报