以下通过例题结合算法做详解
现有如下关系模式:
其中: Teacher(Tno,Tname,Tel,Department,Bid,Bno, Bname,BorrowDate,Rdate)。
Tno一教师编号, Tname一教师姓名, Tel一电话, Department一所在部门,
Bid一图书编码, Bno–图书索书码 Bname一书名, BorrowDate一借书日期, Rdate一还书日期
该关系模式的属性之间具有通常的语义,例如:
教师编号是惟一的,可确定教师姓名及教师的相关信息,
图书索书码可确定书名。图书馆同一索书码的图书可能购买多本,每一本都有唯一的图书编码,当然图书编码也可以决定书名;
教师每次借阅某本图书都有一个具体的借书日期和还书日期,教师还可多次借阅同一本图书,但借书日期不同。
1.根据给出的语义,分析该关系模式的函数依赖,
2. 将该函数依赖集合最小化
3. 运用闭包算法找出所有的候选码。
4. 该关系模式最高满足第几范式?并说明理由。
5. 模式分解要求达到3NF。
6. 验证分解的无损
7. 验证分解的保函
1.根据给出的语义,分析该关系模式的函数依赖
F={Tno->Tname, Tno->Tel, Tno->Department, Bno->Bname, Bid->Bname, Bid->Bno, (Tno,Bid,BorrowDate)->Rdate}
这边需要注意的是最后一个函数依赖,一不小心就会想当然的错写成:
(Tno,Bid)->BorrowDate,Rdate
由于教师可以多次借阅同一本书,因此(Tno,Bid)不能唯一确定BorrowDate和Rdate。但只要人、书、借书日期确定了,就可以知道此书的还书日期了。
2. 将该函数依赖集合最小化
这题可以明显看出函数依赖的传递性,因此去除冗余的函数依赖:Bid->Bname
最严谨的步骤是利用分解规则,假设冗余求闭包的方法来最小化函数依赖集合。这题比较简单不是重点讲述的题目,因此不做赘述。
最小化结果如下:
F={Tno->Tname, Tno->Tel, Tno->Department, Bno->Bname, Bid->Bno, (Tno,Bid,BorrowDate)->Rdate}
3. 运用闭包算法找出所有的候选码。
(Tno,Bid,BorrowDate)F+
X(0)=Tno,Bid,BorrowDate
X(1)=Tno,Bid,BorrowDate,Tname,Tel,Department,Bno,Bname,Rdata
∵X(1)=U
∴候选码:(Tno,Bid,BorrowDate)
4. 该关系模式最高满足第几范式?并说明理由。
最高满足1NF,因为该关系模式中存在非主属性对码的部分函数依赖。
如:Tno->Tname等
该题也存在非主属性对码的传递函数依赖,只不过存在非主属性对码的部分函数依赖已经不满足2NF的要求了,更谈不上判断3NF
5. 模式分解要求达到3NF。
这里给一个分解算法:
转换为3NF既有无损连接又保持函数依赖的分解 算法如下:
根据算法:
1.求最小函数依赖集:
F={Tno->Tname, Tno->Tel, Tno->Department, Bno->Bname, Bid->Bno, (Tno,Bid,BorrowDate)->Rdate}
2.由于R中的所有属性均在F中都出现,所以转下一步。
3_1.对F按具有相同左部的原则分组:
F={Tno->(Tname,Tel,Department), Bid->Bno, Bno->Bname, (Tno,Bid,BorrowDate)->Rdate}
3_2.每一组函数依赖所有涉及的全部属性形成一个属性集,分解成一个关系模式:
R1=(Tno,Tname,Tel,Department)
R2=(Bid,Bno)
R3=(Bno,Bname)
R4=(Tno,Bid,BorrowDate,Rdate)
4.对于R的码形成一个关系模式:
R5=(Tno,Bid,BorrowDate)
5.消除多余的关系模式:
由于R5包含于R4中,因此R5冗余,删除R5
所以最终答案为:
R1=(Tno,Tname,Tel,Department)
R2=(Bid,Bno)
R3=(Bno,Bname)
R4=(Tno,Bid,BorrowDate,Rdate)
注:这边模式分解时,需把关系模式R(Bid,Bno)写在关系模式R(Bno,Bname)前面,否则在下一问验证分解无损的算法中,会出错。两个关系模式中隐含传递性,按照传递的顺序写关系模式,在下一题的修改表时才能修改完整。
6.验证分解的无损
先看算法:
算法比较抽象,我们用实例结合表格做步步分解:
ρ={R1
(1)建立n列k行的表,若属性Aj属于Ui,则在列i行交叉处填上aji,否则填上bij:
(2)对每一个FDi做下列操作:找到Xi所对应的列中具有相同符号的那些行,考察这些行中li列的元素。若其中有ali,则全部改为ali;否则全部改为bmli。其中m是这些行的行号最小值。
①
②
③
④
最后一步,对每一行进行扫描:
补充理解,其他博客看到的,大概是这个道理:
7. 验证分解的保函
这个判断方法其实很简单,对于这道题来说,有
属性集U={Tno,Tname,Tel,Department,Bid,Bno,Bname,BorrowDate,Rdate},
F={Tno->Tname, Tno->Tel, Tno->Department, Bno->Bname, Bid->Bname, Bid->Bno, (Tno,Bid,BorrowDate)->Rdate}
有这样的分解:
R1=(Tno,Tname,Tel,Department) ,F1={Tno->Tname, Tno->Tel, Tno->Department}
R2=(Bid,Bno),F2={Bid->Bno}
R3=(Bno,Bname),F3={Bno->Bname}
R4=(Tno,Bid,BorrowDate,Rdate),F4={(Tno,Bid,BorrowDate)->Rdate}
我们可以直接推出函数依赖有:Tno->Tname,Tno->Tel,Tno->Department,Bid->Bname,Bno->Bname,(Tno,Bid,BorrowDate)->Rdate
通过R2、R3中函数依赖的传递性推出:Bid->Bname
即:F’ = {Tno->Tname, Tno->Tel, Tno->Department, Bno->Bname, Bid->Bname, Bid->Bno, (Tno,Bid,BorrowDate)->Rdate} = F
所以该分解不丢失函数依赖,分解保持函数依赖的特性。
以上,若存在缺陷或错误,亟盼读者不吝指正