查看下面表格,这个表格是将地址列AddRESS冗余到教师课程表中了,这样就会造成数据冗余了。
TNAME |
ADDRESS |
C# |
CNAME |
t1 |
a1 |
c1 |
n1 |
t1 |
a1 |
c2 |
n2 |
t1 |
a1 |
c3 |
n3 |
t2 |
a2 |
c4 |
n4 |
t2 |
a2 |
c5 |
n2 |
t3 |
a3 |
c6 |
n4 |
数据冗余如果一个教师教几门课程,那么这个教师的地址就要重复几次存储。
操作异常由于数据的冗余,在对数据操作时会引起各种异常:
1,修改异常。譬如教师t1教三门课程,在关系中就会有三个元组。如果他的地址变了,这三个元组中的地址都要改变。若有一个元组中的地址未更改,就会造成这个教师的地址不惟一,产生不一致现象。
2,插入异常。如果一个教师刚调来,尚未分派教学任务,那么要将教师的姓名和地址存储到关系中去时,在属性C#和CNAME上就没有值(空值)。在数据库技术中空值的语义是非常复杂的,对带空值元组的检索和操作也十分麻烦。
3,删除异常。如果在图4.1中要取消教师t3的教学任务,那么就要把这个教师的元组删去,同时也把t3的地址信息从表中删去了。这是一种不合适的现象。
正确的做法是将上表“分解”下面两个表:
表R1
TNAME |
ADDRESS |
t1 |
a1 |
t2 |
a2 |
t3 |
a3 |
表R2
TNAME |
C# |
CNAME |
t1 |
c1 |
n1 |
t1 |
c2 |
n2 |
t1 |
c3 |
n3 |
t2 |
c4 |
n4 |
t2 |
c5 |
n2 |
t3 |
c6 |
n4 |
“分解”是解决冗余的主要方法,也是规范化的一条原则:“关系模式有冗余问题,就分解它”
但是分解就是最佳的方法,这也不是绝对的。因为分解时,如果在其中的一个关系中,要用到另外一个关系的属性,就要做连接操作,而连接操作是最浪费时间的操作之一。所以我们要具体情况具体分析。
本章的符号规定
(1)英文字母表首部的大写字母“A,B,C,…”表示单个属性。
(2)英文字母尾部的大写字母“…,U,V,W,X,Y,Z”表示属性集。
(3)大写字母R表示关系模式,小写字母r表示其关系。为方便,有时也用属性名组合写法表示关系模式。若模式有A、B、C三个属性,就用ABC表示关系模式。
(4)属性集{A1,…,An}简写为A1…An。属性集X和Y的并集X∪Y简写为XY。X ∪{A}简写为XA或AX。
函数依赖的定义
定义4.1:
设有关系模式R(U),X和Y是属性集U的子集,函数依赖(functional dependency,简记为FD)是形为X→Y的一个命题,只要r是R的当前关系,对r中任意两个元组t和s,都有t[X]=s[X]蕴涵t[Y]=s[Y],那么称FD X→Y在关系模式R(U)中成立。
例:4.2
零件信息(名称、重量、生产公司名称)
名称 重量 生产公司名称 名称 重量 生产公司名称
T罗丝 80克 北京 T罗丝 80克 北京
T罗丝 90克 北京 T罗丝 90克 天津
W罗丝 90克 上海 W罗丝 90克 上海
R1 R2
注:R1中 名称 → 生产公司名称 成立 (一对一关系)
R1中 生产公司名称 → 名称 成立 (一对一关系)
R2中 名称 → 生产公司名称 不成立 (一对多关系)
R2中 生产公司名称 → 名称 成立 (多对一关系)
例4.3
有一个关于学生选课、教师任课的关系模式:
R(S#,SNAME,C#,GRADE,CNAME,TNAME,TAGE)
属性分别表示学生学号、姓名、选修课程的课程号、成绩、课程名、任课教师姓名和年龄等意义。
如果规定,每个学号只能有一个学生姓名,每个课程号只能决定一门课程,那么可写成下列FD形式:
S#→SNAME C#→CNAME
每个学生每学一门课程,有一个成绩,那么可写出下列FD:
(S#,C#)→GRADE
还可以写出其他一些FD:
C#→(CNAME,TNAME,TAGE) TNAME→TAGERX[≒_8^wQ g儚}Y剉'`齹0?^奲NO?_剉sQ鹼!j_l廱cb3