对关系数据库进行查询统计时,需要查询到用户感兴趣的数据,这就需要对关系及关系间进行一定的运算。本篇主要讲述关系运算和关系的完整性约束,理解关系操作的含义,了解传统的集合运算,掌握关系代数中基本关系运算。通过本篇的学习,读者应该能掌握以下内容:

● 集合的合并、交集、求差、乘积操作

● 关系运算的选择、投影、连接操作

● 关系的完整性约束

● 关系的范式

 

关系运算

关系模型是目前用的最多的数据模型,具有严格的数学理论基础,其主要数学理论基础就是集合运算。关系模型提供了一系列操作的定义,这些操作称为关系代数操作。它可分为两类,一类是集合操作;另一类是关系专用的操作

 

1、集合操作

集合操作是把关系看作元组的集合来进行传统的集合运算,其运算结果仍是关系,前提是参与运算的两个元组具有相同的结构,即含有相同的属性,且对应属性的值域相同。下面对传统的集合运算合并、交集、求差、乘积运算进行逐一说明。

 

集合运算——合并

假设有A、B两个集合

A = {1,3,5,9}, B = {2,3,5,7}

由所有属于集合A或属于集合B的元素组成的集合,叫做集合A与集合B的合并,也称为集合A与集合B的并集,记作:

A U B = {1,2,3,5,7,9}

由此可以推出,设R和S是两个关系,则R U S是合并R和S,合并后的结果仍是关系,结果表中的元组或属于R,或属于S,如图2-10所示:

 

                                

mysql两个数字相乘向下保留两位小数_数据依赖

                                                                                 图 2-10 集合的合并运算

 

集合运算——交集

假设有A、B两个集合

A = {1,3,5,9}, B = {2,3,5,7}

由所有属于集合A且属于集合B的元素组成的集合,叫做集合A与集合B的交集,记作:

A n B = {3,5}

由此可以推出,设R和S是两个关系,则R n S是R和S的交集,求交后的结果仍是关系,结果表中的元组属于R且属于S,如图2-11所示:

 

                     

mysql两个数字相乘向下保留两位小数_元组_02

                                                                 图 2-11 集合的交集运算

 

集合运算——求差

假设有A、B两个集合

A = {1,3,5,9}, B = {2,3,5,7}

由所有属于集合A且不属于集合B的元素组成的集合,叫做集合A与集合B的差,记作:

A - B = {1,9}

由此可以推出,设R和S是两个关系,则R - S是求R和S的差,求差后的结果仍是关系,结果表中的元组属于R且不属于S,如图2-12所示:

 

                              

mysql两个数字相乘向下保留两位小数_数据依赖_03

                                                                  图 2-12 集合的求差运算

集合运算——乘积

假设有A、B两个集合

A = {1,3,5}, B = {2,3}

用A中元素为第一元素,B中元素为第二元素构成有序对,所有这样的有序对组成的集合叫做A与B的乘积(笛卡尔乘积),记作:

A X B = {(1,2),(1,3),(3,2),(3,3),(5,2),(5,3)}

由此可以推出,设R和S是两个关系,则R X S是求R和S的笛卡尔乘积,结果表是R和S的结构之连接,即前n个属性来自R,后m个属性来自S,属性个数等于n+m。结果表的值是由R中的每个元组连接S中的每个元组构成元组的集合。如图2-13所示:

 

                  

mysql两个数字相乘向下保留两位小数_数据依赖_04

                                                   图 2-13 集合的乘积运算

 

2、专门的关系运算

专门的关系运算包括选择、投影、连接和除四种运算。下面介绍常用的三种运算选择、投影和连接。

选择运算

选择运算是单目运算,它从一个关系R中选择出满足给定条件的所有元组,并同R具有相同的结构。图2-14所示为由关系R选出编号为02的老师。

 

                          

mysql两个数字相乘向下保留两位小数_元组_05

                                                                   图 2-14 专门关系运算—选择运算

 

投影运算

投影运算也是单目运算,它从一个关系R所有属性中选择某些指定属性,组成一个新的关系。选择运算选取关系的某些行,而投影运算选取关系的某些列,是从一个关系出发构造其垂直子集的运算。图2-15所示为由关系R中选出所有老师的姓名和简介。

 

mysql两个数字相乘向下保留两位小数_mysql两个数字相乘向下保留两位小数_06

图 2-15 专门关系运算—投影运算

连接运算

连接运算属于二目运算,是从两个关系元组的所有组合中选取满足一定条件的元组,由这些元组形成连接运算的结果关系,其中条件表达式涉及到两个关系中属性的比较,该表达式的取值为真或假。图2-16所示为对课程表和老师表在老师编号相等的条件下进行了连接,在新的关系中仅选出名称、姓名两个属性,即在新关系中再进行一次投影运算,这样得到了所有老师编号为01的课程名称和老师姓名。

 

                        

mysql两个数字相乘向下保留两位小数_元组_07

                                                      图 2-16 专门关系运算—连接运算

 

关系的完整性

关系模型的完整性主要分为以下四类。

(1)域完整性。关系模型中,每列属性的取值应是域所确定的值。即属性的取值范围应在其值集或值域内。例如在课程表中,名称属性值是汉字或英文字符串,所以不能取出数值来,同时,名称是课程的主要特征,要求必须有课程名称,即名称属性不能为空。

(2)实体完整性关系模型中每一个表就是一个实体,在现实世界中,实体是可区分的,即它们具有唯一标识。实体映射到关系模型后,每个表也应该具有唯一的标识,这个标识称为主键,用于标识表中唯一的元组。主键不能为空,如果主键为空,则说明存在某个不可标识的实体,而这和唯一标识相矛盾,即不存在这样的实体。

(3)参照完整性。实体完整性是一个表内的约束,参照完整性是在不同表之间或同一表的不同元组之间的约束。例如课程表中的老师编号属性给出了老师的编号,但在课程表中并没有老师的信息,要想得到老师的信息,就必须通过表中的老师编号到老师表中去查找。由于编号在老师表中是主键,这样能够找到唯一的一行与该老师编号相对应。对于老师表中的编号属性来说,通常定义是该表的外关键字,简称外键,同时,编号属性也是老师表的主键。如图2-17所示:

 

                                 

mysql两个数字相乘向下保留两位小数_元组_08

                                                                         图 2-17 老师表与课程表的参照约束

从上图可以看出,课程表中老师编号属性的每一个值都能在老师表中找到唯一的一行元组,即能找到唯一的老师与其对应,则称为参照是完整的,否则,则称为参照不完整的。

(4)用户定义的完整性。用户定义的完整性用于满足用户对数据的语义要求,是由用户对数据库施加的约束条件。例如,课程视频长度不能超过30分钟、老师必须具备专业知识等约束条件。

 

关系模型的规范化

关系模型的规范化是指面对一个现实问题,如何选择一个比较好的关系模式集合。

当一个关系模式设计的不够规范时,就会出现插入异常、删除异常、冗余过多等问题。例如图2-18学生选课表中,其中编号、姓名属性是表的主键,在实际应用中,该表会存在插入、删除、冗余过多等异常。

 

                     

mysql两个数字相乘向下保留两位小数_数据依赖_09

                                                                  图 2-18 学生选课表

(1)插入异常。比如一个刚刚成立的系,但尚未招收学生,则因属性编号、姓名为空,导致系名、系主任等信息无法存入数据库;同样,没被学生选修的课程也无法存入数据库。

(2)删除异常。如一个系的学生毕业了,删除学生记录时会将系主任、系名等信息一起删除。

(3)冗余过多。如一个系的系名、系主任姓名都有与该系学生每门课的成绩出现的次数一样多。既浪费存储空间又要付出很大的代价来维护数据库的完整性。当系主任更换后,必须逐一修改该系学生选修课程的每一个元组。

从上面的例子可以看出,一个好的关系模式不应当发生插入异常和删除异常,且数据冗余尽可能地少。引起数据冗余及其操作异常的原因在于关系的结构。现实世界中的许多事物都可以独立存在、独立地被标识、相互间又密切关联。如果将多个本该是独立存在地、具有不同标识的事物用一个关系描述,那么不可能找到这样一个属性集,它既是这个关系的标识,又是包含在其中的各个不同事物的标识,正是由于关系模式的属性之间存在过多的数据依赖,从而出现了数据冗余和更新的异常。

数据依赖是指关系中属性值之间的相互联系,它是现实世界属性间相互联系的体现,是数据之间的内在联系,是语义的体现。现在人们已经提出了许多种类型的数据依赖,其中最重要的是函数依赖

函数依赖比较容易理解,且普遍地存在于现实生活中。在学生选课表中,因一个编号仅对应一个学生,一个学生只在一个系注册学习。因而,当编号的值确定后,姓名和所在系的值也就唯一确定了。当关系模式属性间存在这个关系时,我们就说姓名和所在系的值依赖于学号,即编号决定姓名和系名

在学生选课表中除了姓名和系名依赖编号外,还存在其它数据依赖,如一个系只有一个系主任,因此系名依赖于系主任;再如,每个学生学习一门课都有一个成绩,因此成绩依赖于学号和课程名称。因为学生选课表中数据依赖过多,导致发生更新异常和数据冗余问题。

解决办法是将关系模式分解成若干只有单一数据依赖的关系模式,因为关系模式学生选课表出现异常问题是由于属性之间存在过多的数据依赖造成的,分解的目的就是减少属性间过多的数据依赖,已期消除关系模式中出现的异常。学生选课表关系模式分解成如图2-19所示的三个表。

 

                              

mysql两个数字相乘向下保留两位小数_元组_10

                                                             图 2-19 规范化后的三个关系表

学生选课表规范化后,分解为学生表、成绩表、系表三个表,解决了关系模式多数据依赖的问题,每个表都是单一的数据依赖。规范化后虽然解决了数据冗余、更新异常的问题,但检索效率明显降低了,需要多表查询因此,一个关系是否要进行规范化,应当本着具体问题具体分析的原则进行处理事实上,如果在一个关系上主要执行的是查询操作,未必一定要规范化通过适当地增加一些关系或者在应用程序中注意到更新一致性的维护,非规范化的弊端是可以避免的。但是,如果在关系上要进行频繁的更新操作,还是要采用规范化的方式比较好。

 

关系的范式

前面讨论了关系模式没有规范化所引起的异常问题,因此规范化对数据库设计有着重要的意义。所以建立科学的,规范的数据库是需要满足一些约束条件的,在关系型数据库中这些约束条件被称为范式根据一个关系满足数据依赖程度的不同,人们提出了第一范式(1NF)、第二范式(2NF)、第三范式(3NF)。当然从理论上研究还有其他范式,但实际意义不大,这里不作讨论。

(1)第一范式(1NF)。表中所有的属性都是不可再分的。如学生选课表中系名和系主任就不能合并为一个属性,因为违反了第一范式。当前所有的关系数据库都支持第一范式,即要求表属性都是原子属性,即属性的不可分性。

(2)第二范式(2NF)。要求在满足第一范式的前提下,除去所有不完全依赖于主键的属性(部分依赖)。如学生选课表中,就存在不满足第二范式的问题,系名和系主任属性部分依赖于编号属性(主键),因此存在更新异常、数据冗余的问题。第二范式要求所有非主属性(不属于主键的属性)都完全依赖于主键

(3)第三范式(3NF)。要求关系在满足第二范式的前提下,除去所有传递依赖于主键的属性,即关系中不含有对主键的传递依赖。传递依赖就是间接依赖。例如在关系R(学号,宿舍,费用)中,费用就间接依赖于学号。