本文中的Student、Course、SC表依次如下:
连接查询
等值与非等值查询
连接查询WHERE子句中用来连接两个表的条件称为连接条件或连接谓词
[<表名1>.] <列名1> <比较运算符> [<表名2>.] <列名2>
e.g. Student.Sno = SC.Sno
比较运算符主要有= > < >= <= != <>等
[<表名1>.] <列名1> BETWEEN [<表名2>.] <列名2> AND [<表名3>.] <列名3>
连接条件中的各连接字段类型必须是可比的,但名字不一定要相同
例3.49:查询每个学生及其选修课程的情况
SELECT *
FROM Student,SC
WHERE Student.Sno = SC.Sno;
运行结果如图:
这里书上明显写的就比较繁琐:
SELECT Student.*,SC.*
FROM Student,SC
WHERE Student.Sno = SC.Sno;
在等值连接中把目标列中重复的属性列去掉则为自然连接
例3.50:对例3.49用自然连接完成
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
--这里的Sno一定要加Student来修饰,因为他在两个表格中是有重复出现的
--而其他属性都是唯一存在的,所以直接列举出来就好
FROM Student,SC
WHERE Student.Sno = SC.Sno;
一条SQL语句即可同时完成选择和连接查询
例3.51:查询选修2号课程且成绩在86分以上的所有同学的学号和姓名
这道题要的学号我们暂且使用SC表中的
SELECT SC.Sno,Student.Sname
FROM SC,Student
--FROM操作即为连接操作
WHERE Student.Sno = SC.Sno AND SC.Cno = '2' AND SC.Grade > 86;
--WHERE AND操作即为选择操作
自身连接
顾名思义,就是一个表和自己相连
例3.52:查询每一门课的间接选修课(先修课的先修课)
SELECT FIRST.Cno SECOND.Cpno
FROM Course FIRST,Course SECOND
WHERE SECOND.Cno = FIRST.Cpno;
SELECT FIRST.Cno SECOND.Cpno
FROM Course FIRST,Course SECOND
--WHERE SECOND.Cno = FIRST.Cpno;
这里如果去掉最后一行的修饰条件的话,即是两张表的笛卡尔积
因为在标准SQL语句中自身连接后不应该出现NULL的组,所以调试一下代码,获得如下的结果
SELECT * --FIRST.Cno,SECOND.Cpno
FROM Course FIRST,Course SECOND
WHERE SECOND.Cno = FIRST.Cpno;
比对两组结果的第三行可推测其中的原理:
现象:操作系统(4)的先行课是数据处理(6),然而数据处理(6)是没有先行课的,也就是先行课列属性值为NULL,不符合题目要求
推测:可能在这里NULL也被当成是一种值,SQL没有进行处理优化,可能只是单纯的比较了FIRST.Cpno = Second.Cno,相等的话就直接把Second.Cpno的值打印出来,没有判断Second.Cpno的值是否是NULL
外连接
简而言之就是空余的地方被赋予NULL的一种连接
左外连接:列出左边关系中所有的元组
右外连接:列出右边关系中所有的元组
例3.53
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student LEFT OUTER JOIN SC
ON (Student.Sno = SC.Sno);
自己又试了一下右外连接,结果右表NULL的地方,左边相对应的元组直接舍弃了,结果如下:
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student RIGHT OUTER JOIN SC
ON (Student.Sno = SC.Sno);
又试了一下把LEFT去掉,发现报错了,看来外连接的时候必须要指定是左外连接还是右外连接
!!这是错误的代码!!
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student OUTER JOIN SC
ON (Student.Sno = SC.Sno);
在做外连接的时候,SELECT指定要连接的属性,这个是自己根据表格去指定,一般格式应如下:
!!外连接的一般格式!!
SELECT 属性
FROM 第一个表 LEFT/RIGHT OUTER JOIN 第二个表
ON 条件
对于此题,又换了一种写法:
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student,SC
WHERE Student.Sno = SC.Sno;
运行结果是这样的:
看来如果直接用WHERE来说明条件进行连接,应该是舍弃含有NULL的元组
多表连接
多表连接就是三个及以上的表格进行连接,连接的过程是两两进行连接(1和2连接成12,再与3连接成为123)
例3.54:查询每个学生的学号、姓名、选修的课程名及成绩
SELECT Student.Sno,Student.Sname,Course.Cname,SC.Grade
--这里我个人为了保险起见,是把所有属性的所属表也都说明了出来
--实际情况是,只要是几个表中唯一的属性值就可以不用将其所属的表写出来
FROM Student,Course,SC
WHERE Student.Sno = SC.Sno AND Course.Cno = SC.Cno;
//WHERE进行选择 AND进行连接
小结:
这两次实验其实上理论课的时候好好听讲,弄清楚各个语句的逻辑含义,做实验的时候其实誊抄上例题后,自己就可以写成代码,总体上还是比较容易的