一个数据库中的多个表之间一般都存在某种内在联系,它们共同提供有用的信息。前面的查询都是针对一个表进行的。若一个查询同时涉及两个以上的表,则称之为连接查询。连接查询主要包括等值连接、非等值连接查询、自身连接查询(连接 二、自身连接)、外连接查询(连接 三、外连接)和复合条件连接查询(连接 四、复合条件连接)。
| 一、 | 等值与非等值连接查询 | |||
| 用来连接两个表的条件称为连接条件或连接谓词,其一般格式为: [<表名1>.]<列名1> <比较运算符> [<表名2>.]<列名2> 其中比较运算符主要有:=、>、<、>=、<=、!=<=、!= 此外连接谓词词还可以使用下面形式: [<表名1>.]<列名1> BETWEEN [<表名2>.]<列名2> AND [<表名2>.]<列名3> 当连接运算符为=时,称为等值连接。使用其它运算符称为非等值连接。 |
||||
|
连接谓词中的列名称为连接字段。连接条件中的各连接字段类型必须是可比的,但不必是相同的。例如,可以都是字符型,或都是日期型;也可以一个是整型,另一个是实型,整型和实型都是数值型,因此是可比的。但若一个是字符型,另一个是整数型就不允许了,因为它们是不可比的类型。 |
||||
| 例32 | 查询每个学生及其选修课程的情况 | |||
|
学生情况存放在Student表中,学生选课情况存放在SC表中,所以本查询实际上同时涉及Student与SC两个表中的数据。这两个表之间的联系是通过两个表都具有的属性Sno实现的。要查询学生及其选修课程的情况,就必须将这两个表中学号相同的元组连接起来。这是一个等值连接。完成本查询的SQL语句为: |
||||
| 例33 | 自然连接Student和SC表 | |||
|
||||
|
在本查询中,由于Sname、 Ssex、 Sage、Sdept、Cno和Grade属性列在Student与SC表中是唯一的,因此引用时可以去掉表名前缀。而Sno在两个表都出现了,因此引用时必须加上表名前缀。该查询的执行结果不再出现SC.Sno列。 |
||||
| 二、 |
自身连接 |
|||
| 连接操作不仅可以在两个表之间进行,也可以是一个表与其自己进行连接,这种连接称为表的自身连接。 | ||||
| 例34 | 查询每一门课的间接先修课(即先修课的先修课) | |||
|
我们先来分析一下,题目要求查询每一门课程的先修课的先修课,在“课程”表即Course关系中,只有每门课的直接先修课信息,而没有先修课的先修课,要得到这个信息,必须先对一门课找到其先修课,再按此先修课的课程号,查找它的先修课程,这相当于将Course表与其自身连接后,取第一个副本的课程号与第二个副本的先修课号做为目标列中的属性。具体写SQL语句时,为清楚起见,我们可以为Course表取两个别名,一个是FIRST,另一个是SECOND,也可以在考虑问题时就把Course表想成是两个完全一样表,一个是FIRST表,另一个是SECOND表。如下所示: |
||||
| 三、 | 外连接 | |||
| 在通常的连接操作中,只有满足连接条件的元组才能作为结果输出,如在例32和例33的结果表中没有关于95003和95004两个学生的信息,原因在于他们没有选课,在SC表中没有相应的元组。但是有时我们想以Student表为主体列出每个学生的基本情况及其选课情况,若某个学生没有选课,则只输出其基本情况信息,其选课信息为空值即可,这时就需要使用外连接(Outer Join)。外连接的运算符通常为*。有的关系数据库中也用+。 | ||||
| 这样,我们就可以如下改写例33: | ||||
|
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade |
||||
| 四、 | 复合条件连接 | |||
| 上面各个连接查询中,WHERE子句中只有一个条件,即用于连接两个表的谓词。WHERE子句中有多个条件的连接操作,称为复合条件连接。 | ||||
| 例35 | 查询选修2号课程且成绩在90分以上的所有学生 | |||
| SELECT Student.Sno, Sname FROM Student, SC WHERE Student.Sno=SC.Sno AND SC.Cno='2' AND SC.Grade>90; |
||||
| 连接操作除了可以是两表连接,一个表与其自身连接外,还可以是两个以上的表进行连接,后者通常称为多表连接。 | ||||
| 例36 | 查询每个学生及其选修的课程名其及成绩 | |||
| SELECT Student.Sno, Sname, Course.Cname, SC.Grade FROM Student, SC, Course WHERE Student.Sno=SC.Sno and SC.Cno=Course.Cno; |
