1、第三章 关系数据库标准语言SQL,3.1 SQL概述 3.2 学生课程数据库 3.3 数据定义 3.4 数据查询 3.5 数据更新 3.6 视图,3.1 SQL概述,一、SQL的产生与发展 1974年IBM圣约瑟实验室的Boyce和Chamberlin为关系数据库管理系统设计的一种查询语言,当时称为SEQUEL语言 (Structured English Query Language),后简称为SQL; 1986年ANSI(美国国家标准局)着手制定SQL标准-SQL86; SQL86主要内容:模式定义、数据操作、嵌入式SQL等内容 1987年,ISO(国际标准组织) 通过SQL86标准; 后来
2、经过了SQL89、SQL92、SQL99、SQL2003的发展,,,二、SQL的特点,1. 综合统一 2. 高度非过程化 3. 面向集合的操作方式 4. 以同一种语法结构提供两种使用方法 5. 语言简洁,易学易用,三、SQL的基本概念,3.2 学生课程数据库,Student,Course,SC,3.3 数 据 定 义,表3.2 SQL的数据定义语句,3.3.1 模式的定义与删除,一、定义模式CREATE SCHEMA AUTHORIZATION,例如1 定义一学生课程模式 CREATE SCHEMA “S-T” AUTHORIZATION WANC 或 CREATE SCHEMA AUTHOR
3、IZATION WANC,定义模式实际上定义了一个命名空间,在这个空间中可以进一步定义该模式包含的数据库对象,例如基本表、视图、索引等。,3.3.1 模式的定义与删除,可以在模式创建的同时在这个模式中定义中进一步创建基本表、视图、定义授权。 CREATE SCHEMA AUTHORIZATION |,例如3 CREATE SCHEMA TEST AUTHORIZATION ZHANG CREATE TABLE TAB1 (COL1 SMALLINT,COL2 INTCOL3 CHAR(20)COL4 DATECOL5 CHAR(20);,3.3.1 模式的定义与删除,二、删除模式DROP SC
4、HEMA ,其中:CASCADE: 联级RESTRICT:限制,例如4 DROP SCHEMA ZHANG CASCAD,3.3.2 基本表的定义、删除与修改,CREATE TABLE ( , , ); :所要定义的基本表的名字 :组成该表的各个属性(列) :涉及相应属性列的完整性约束条件 :涉及一个或多个属性列的完整性约束条件,一、定义基本表,例题,例5 建立一个“学生”表Student,它由学号Sno、姓名Sname、性别Ssex、年龄Sage、所在系Sdept五个属性组成。其中学号为主码,并且姓名取值也唯一。,常用完整性约束 主码约束: PRIMARY KEY 唯一性约束:UNIQUE
5、非空值约束:NOT NULL 外码:FOREIGN KEY 参照完整性约束,CREATE TABLE Student(Sno CHAR(9) PRIMARY KEY,Sname CHAR(20) UNIQUE, Ssex CHAR(2) ,Sage SMALLINT,Sdept CHAR(20);,例题,例6 建立一个“课程”表Course。CREATE TABLE Course(Cno CHAR(4) PRIMARY KEY , Cname CHAR(40),Cpno CHAR(4),Ccredit SMALLINT,FOREIGN KEY (Cpno) REFERENCES Course(
6、Cno) );,例题,例7 建立一个“学生选课”表SC,它由学号Sno、课程号Cno,修课成绩Grade组成,其中(Sno, Cno)为主码。 CREATE TABLE SC(Sno CHAR(9) ,Cno CHAR(4) , Grade SMALLINT,PRIMARY key (Sno, Cno),FOREIGN KEY (Sno) REFERENCES Student(Sno),FOREIGN KEY (Cno) REFERENCES Course(Cno) );,二、数据类型,CHAR(n) 长度为n的定长字符串。 VARCHAR(n) 最大长度为n的变长字符串。 INT 全字长二进
7、制整数。 SMALLINT 半字长二进制整数。 FLOAT 双字长浮点数。 DATE 日期型,格式为YYYY-MM-DD。 TIME 时间型,格式为HH.MM.SS。 TIMESTAMP 日期加时间。,注意:不同的DBMS支持的数据类型不完全相同,三、模式与表,每一个基本表都属于某一个模式,一个模式包含多个基本表。有三种方法定义基本表所属的模式。 方法一:在表名中明显的给出模式名CREATE TABLE “S-T”.Stuent();CREATE TABLE “S-T”. Course();CREATE TABLE “S-T”.SC(); 方法二:在创建模式语句中同时创建表(如:例3) 方法三
8、:设置所属的模式Set scarch_path to “S-T”,PUBLIC,四、修改基本表,ALTER TABLE ADD 完整性约束 DROP MODIFY ;,:要修改的基本表 ADD子句:增加新列和新的完整性约束条件 DROP子句:删除指定的完整性约束条件 MODIFY子句:用于修改列名和数据类型 说明:没有删除列的功能,例题,例8 向Student表增加“入学时间”列,其数据类型为日期型。ALTER TABLE Student ADD Scome DATE; 不论基本表中原来是否已有数据,新增加的列一律为空值。,例9 将年龄的数据类型改为整数。 ALTER TABLE Studen
9、t MODIFY Sage SMALLINT; 注:修改原有的列定义有可能会破坏已有数据,例10 删除学生姓名必须取唯一值的约束。ALTER TABLE Student DROPUNIQUE(Sname);,四、修改基本表,删除属性列间接删除 把表中要保留的列及其内容复制到一个新表中 删除原表 再将新表重命名为原表名,DROP TABLE RESTRICT|CASCADE; RESTRICT:有限制条件的删除。基本表不能被其它表作为参照约束所引用,不能有视图,不能触发器,不能有存储程序和函数等。若有则不能删除。 CASCADE:无条件删除(相关依赖的对象一起删除)。,例11 删除Student
10、表DROP TABLE Student ;,五、删除基本表,3.3.2 建立与删除索引,建立索引是加快查询速度的有效手段 DBA或表的属主(即建立表的人)根据需要建立 有些DBMS自动建立以下列上的索引PRIMARY KEYUNIQUE 维护索引DBMS自动完成 使用索引DBMS自动选择是否使用索引以及使用哪些索引,一、建立索引,语句格式 CREATE UNIQUE CLUSTER INDEX ON (, ); 用指定要建索引的基本表名字 索引可以建立在该表的一列或多列上,各列名之间用逗号分隔 用指定索引值的排列次序,升序:ASC,降序:DESC。缺省值:ASC UNIQUE表明此索引的每一个
11、索引值只对应唯一的数据记录 CLUSTER表示要建立的索引是聚簇索引,例题,例13 CREATE CLUSTER INDEX Stusname ON Student(Sname);,例14 为学生-课程数据库中的Student,Course,SC三个表建立索引。其中Student表按学号升序建唯一索引,Course表按课程号升序建唯一索引,SC表按学号升序和课程号降序建唯一索引。 CREATE UNIQUE INDEX Stusno ON Student(Sno); CREATE UNIQUE INDEX Coucno ON Course(Cno); CREATE UNIQUE INDEX S
12、Cno ON SC(Sno ASC,Cno DESC);,唯一值索引 对于已含重复值的属性列不能建UNIQUE索引 对某个列建立UNIQUE索引后,插入新记录时DBMS会自动检查新记录在该列上是否取了重复值。这相当于增加了一个UNIQUE约束,聚簇索引,建立聚簇索引后,基表中数据也需要按指定的聚簇属性值的升序或降序存放。也即聚簇索引的索引项顺序与表中记录的物理顺序一致 例: CREATE CLUSTER INDEX Stusname ON Student(Sname); 在Student表的Sname(姓名)列上建立一个聚簇索引,而且Student表中的记录将按照Sname值的升序存放。,在一
13、个基本表上最多只能建立一个聚簇索引 聚簇索引的用途:对于某些类型的查询,可以提高查询效率 聚簇索引的适用范围很少对基表进行增删操作很少对其中的变长列进行修改操作,二、删除索引,DROP INDEX ;删除索引时,系统会从数据字典中删去有关该索引的描述。 例15 删除Student表的Stusname索引。DROP INDEX Stusname;,3.4 查 询,SELECT ALL|DISTINCT , FROM , WHERE GROUP BY HAVING ORDER BY ASC|DESC ;,SELECT子句:指定要显示的属性列 FROM子句:指定查询对象(基本表或视图) WHERE子
14、句:指定查询条件GROUP BY子句:对查询结果按指定列的值分组,该属性列值相等的元组为一个组。通常会在每组中作用集函数。 HAVING短语:筛选出只有满足指定条件的组 ORDER BY子句:对查询结果表按指定列值的升序或降序排序,语句格式,学生-课程数据库,Student,Course,SC,学生表:Student(Sno,Sname,Ssex,Sage,Sdept) 课程表:Course(Cno,Cname,Cpno,Ccredit) 学生选课表:SC(Sno,Cno,Grade),3.4.1 单表查询,查询仅涉及一个表,是一种最简单的查询操作 一、选择表中的若干列,1.查询指定的若干列
15、例1 查询全体学生的学号与姓名。 SELECT Sno,Sname FROM Student; 例2 查询全体学生的姓名、学号、所在系。 SELECT Sname,Sno,Sdept FROM Student;,2.查询全部列 例3 查询全体学生的详细记录。 SELECT Sno,Sname,Ssex,Sage,Sdept FROM Student; 或 SELECT * FROM Student;,3.查询经过计算的值,SELECT 子句的为表达式 算术表达式、字符串常量、函数、列别名等,例4 查全体学生的姓名及其出生年份。 SELECT Sname,2006-Sage FROM Stude
16、nt;,输出结果:,例5 查询全体学生的姓名、出生年份和所有系,要求用小写字母表示所有系名。 SELECT Sname,Year of Birth: ,2006-Sage,ISLOWER(Sdept)FROM Student;,结果为:,例5 使用列别名改变查询结果的列标题,SELECT Sname NAME,Year of Birth: BIRTH,2006-Sage BIRTHDAY,ISLOWER(Sdept) DEPARTMENTFROM Student;,输出结果:,二、选择表中的若干元组,在SELECT子句中使用DISTINCT短语,例6 查询选修了课程的学生学号。 (1) SEL
17、ECT SnoFROM SC;或(默认 ALL)SELECT ALL SnoFROM SC,(2) SELECT DISTINCT SnoFROM SC;,(1)结果:,(2)结果:,SC,注意:DISTINCT短语的作用范围是所有目标列 例:查询选修课程的各种成绩 错误的写法 SELECT DISTINCT Cno,DISTINCT Grade FROM SC; 正确的写法SELECT DISTINCT Cno,GradeFROM SC;,1. 消除取值重复的行,2.查询满足条件的元组,WHERE子句常用的查询条件,(1) 比较大小,在WHERE子句的中使用比较运算符 =,=,!,!, 逻辑
18、运算符NOT + 比较运算符 例7 查询 计算机科学系的全体学生的名单。,例8 查询所有年龄在20岁以下的学生姓名及其年龄。,SELECT Sname,Sage FROM Student WHERE NOT Sage = 20;,SELECT Sname,Sage FROM Student WHERE Sage 20;,或,例9 查询考试成绩有不及格的学生的学号。,SELECT DISTING Sno FROM SC WHERE Grade 60;,SELECT Sname FROM Student WHERE Sdept =CS;,(2) 确定范围,使用谓词 BETWEEN AND NOT
19、BETWEEN AND ,例10 查询年龄在2023岁(包括20岁和23岁)之间的学生的姓名、系别和年龄。SELECT Sname,Sdept,Sage FROM Student WHERE Sage BETWEEN 20 AND 23;,例11 查询年龄不在2023岁之间的学生姓名、系别和年龄。 SELECT Sname,Sdept,SageFROM StudentWHERE Sage NOT BETWEEN 20 AND 23;,(3) 确定集合,使用谓词 IN , NOT IN :用逗号分隔的一组取值,例12查询信息系(IS)、数学系(MA)和计算机科学系(CS)学生的姓名和性别。 SE
20、LECT Sname,Ssex FROM Student WHERE Sdept IN ( IS,MA,CS );,例13查询既不是信息系、数学系,也不是计算 机科学系的学生的姓名和性别。 SELECT Sname,Ssex FROM StudentWHERE Sdept NOT IN ( IS,MA,CS );,(4) 字符串匹配,NOT LIKE ESCAPE :指定匹配模板匹配模板:固定字符串或含通配符的字符串当匹配模板为固定字符串时,可以用 = 运算符取代 LIKE 谓词用 != 或 运算符取代 NOT LIKE 谓词,% (百分号) 代表任意长度(长度可以为0)的字符串 例:a%b表
21、示以a开头,以b结尾的任意长度的字符串。如acb,addgb,ab 等都满足该匹配串 _ (下横线) 代表任意单个字符 例:a_b表示以a开头,以b结尾的长度为3的任意字符串。如acb,afb等都满足该匹配串,通配符,ESCAPE 短语:,当用户要查询的字符串本身就含有 % 或 _ 时,要使用ESCAPE 短语对通配符进行转义。,1) 匹配模板为固定字符串,例14 查询学号为200215121的学生的详细情况。 SELECT * FROM Student WHERE Sno LIKE 200215121 ; 等价于: SELECT * FROM Student WHERE Sno = 2002
22、15121 ;,2) 匹配模板为含通配符的字符串,例15 查询所有姓刘学生的姓名、学号和性别。SELECT Sname,Sno,SsexFROM StudentWHERE Sname LIKE 刘%;,例16 查询姓“欧阳“且全名为三个汉字的学生的姓名。SELECT SnameFROM StudentWHERE Sname LIKE 欧阳_;,例17 查询名字中第2个字为“阳“字的学生的姓名和学号。SELECT Sname,SnoFROM StudentWHERE Sname LIKE _阳%;,例18 查询所有不姓刘的学生姓名。 SELECT Sname,Sno,Ssex FROM Stud
23、ent WHERE Sname NOT LIKE 刘%;,3) 使用换码字符将通配符转义为普通字符,例19 查询DB_Design课程的课程号和学分。SELECT Cno,Ccredit FROM CourseWHERE Cname LIKE DB_Design ESCAPE ; 例20 查询以“DB_“开头,且倒数第3个字符为 i的课程的详细情况。SELECT * FROM CourseWHERE Cname LIKE DB_%i_ _ ESCAPE ;,(5) 涉及空值的查询,使用谓词 IS NULL 或 IS NOT NULL“IS NULL” 不能用 “= NULL” 代替,例21 某
24、些学生选修课程后没有参加考试,所以有选课记录,但没有考试成绩。查询缺少成绩的学生的学号和相应的课程号。SELECT Sno,Cno FROM SCWHERE Grade IS NULL;,例22 查所有有成绩的学生学号和课程号。 SELECT Sno,Cno FROM SC WHERE Grade IS NOT NULL;,(6) 多重条件查询,用逻辑运算符AND和 OR来联结多个查询条件AND的优先级高于OR可以用括号改变优先级 可用来实现多种其他谓词NOT INNOT BETWEEN AND ,例23 查询计算机系年龄在20岁以下的学生姓名。SELECT SnameFROM Student
25、WHERE Sdept= CS AND Sage20;,改写例12,例12 查询信息系(IS)、数学系(MA)和计算机科学系(CS)学生的姓名和性别。 SELECT Sname,Ssex FROM Student WHERE Sdept IN ( IS,MA,CS ); 可改写为: SELECT Sname,Ssex FROM Student WHERE Sdept= IS OR Sdept= MA OR Sdept= CS ;,改写例10,例10 查询年龄在2023岁(包括20岁和23岁)之间学生的姓名、系别和年龄。 SELECT Sname,Sdept,Sage FROM Student
26、WHERE Sage BETWEEN 20 AND 23;可改写为: SELECT Sname,Sdept,Sage FROM Student WHERE Sage=20 AND Sage=23;,三、对查询结果排序,使用ORDER BY子句可以按一个或多个属性列排序升序:ASC;降序:DESC;缺省值为升序 当排序列含空值时 ASC:排序列为空值的元组最后显示 DESC:排序列为空值的元组最先显示,例24 查询选修了3号课程的学生的学号及其成绩,查询结果按分数降序排列。 SELECT Sno,GradeFROM SCWHERE Cno= 3 ORDER BY Grade DESC;,例25
27、查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列。 SELECT *FROM StudentORDER BY Sdept,Sage DESC;,四、使用集函数,5类主要集函数 计数 COUNT(DISTINCT|ALL *) COUNT(DISTINCT|ALL ) 计算总和 SUM(DISTINCT|ALL ) 计算平均值 AVG(DISTINCT|ALL ),求最大值 MAX(DISTINCT|ALL ) 求最小值 MIN(DISTINCT|ALL )DISTINCT短语:在计算时要取消指定列中的重复值 ALL短语:不取消重复值(为缺省值),例26 查询学生总
28、人数。SELECT COUNT(*)FROM Student;例27 查询选修了课程的学生人数。SELECT COUNT(DISTINCT Sno)FROM SC; 注:用DISTINCT以避免重复计算学生人数,例28 计算1号课程的学生平均成绩。SELECT AVG(Grade)FROM SCWHERE Cno= 1 ;,例30 查询学生200215012选修课程的总学分数。SELECT SUM(Gcredit)FROM SC,CourseWHER Sno= 200215012 AND SC.Cno=Course.Cno;,例29 查询选修1号课程的学生最高分数。SELECT MAX(Gra
29、de)FROM SCWHER Cno= 1 ;,五、对查询结果分组,使用GROUP BY子句分组,细化集函数的作用对象未对查询结果分组,集函数将作用于整个查询结果对查询结果分组后,集函数将分别作用于每个组 例31 求各个课程号及相应的选课人数。SELECT Cno,COUNT(Sno)FROM SCGROUP BY Cno;,GROUP BY子句的作用对象是查询的中间结果表; 分组方法:按指定的一列或多列值分组,值相等的为一组; 使用GROUP BY子句后,SELECT子句的列名列表中只能出现分组属性和集函数。,使用HAVING短语筛选最终输出结果,例32 查询选修了3门以上课程的学生学号。
30、SELECT SnoFROM SCGROUP BY SnoHAVING COUNT(*) 3;,补充例 查询有3门以上课程是90分以上的学生的学号及(90分以上的)课程数 SELECT Sno, COUNT(*)FROM SC WHERE Grade=90 GROUP BY Sno HAVING COUNT(*)3;,只有满足HAVING短语指定条件的组才输出 HAVING短语与WHERE子句的区别:作用对象不同 WHERE子句作用于基表或视图,从中选择满足条件的元组。 HAVING短语作用于组,从中选择满足条件的组。,3.4.2 连接查询,同时涉及多个表的查询称为连接查询,用来连接两个表的条
31、件称为连接条件或连接谓词 一般格式: . .比较运算符:=、=、. BETWEEN . AND . ,连接字段 连接谓词中的列名称为连接字段; 连接条件中的各连接字段类型必须是可比的,但不必是相同的。,连接操作的执行过程,嵌套循环法(NESTED-LOOP) 首先在表1中找到第一个元组,然后从头开始扫描表2,逐一查找满足连接件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组。 表2全部查找完后,再找表1中第二个元组,然后再从头开始扫描表2,逐一查找满足连接条件的元组,找到后就将表1中的第二个元组与该元组拼接起来,形成结果表中一个元组。 重复上述操作,直到表1中的全部元
32、组都处理完毕,一、等值与非等值连接查询,等值连接 例33 查询每个学生及其选修课程的情况。 SELECT Student.*,SC.* FROM Student,SC WHERE Student.Sno = SC.Sno;,自然连接,等值连接的一种特殊情况,把目标列中重复的属性列去掉。 例34 对例33用自然连接完成。SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,GradeFROM Student,SCWHERE Student.Sno = SC.Sno;,二、自身连接,一个表与其自己进行连接,称为表的自身连接 需要给表起别名以示区别 由于所有属性名
33、都是同名属性,因此必须使用别名前缀,二、自身连接,FIRST表(Course表),SECOND表(Course表),查询结果,例35 查询每一门课的间接先修课(即先修课的先修课)SELECT FIRST.Cno,SECOND.CpnoFROM Course FIRST,Course SECONDWHERE FIRST.Cpno = SECOND.Cno;,三、外连接(Outer Join),外连接与普通连接的区别 普通连接操作只输出满足连接条件的元组 外连接操作以指定表为连接主体,将主体表中不满足连接条件的元组一并输出,左连接LEFT OUT JOIN ON 右连接RIGHT OUT JOIN
34、 ON 外连接FULL JOIN ON,例 36 查询每个学生及其选修课程的情况包括没有选修课程的学生-用外连接操作 SELECT Student.Sno,Sname,Ssex, Sage,Sdept,Cno,GradeFROM Student LEFT OUT JOIN SC ON (Student.SNO=SC.SNO);,或:FROM Student LEFT OUT JOIN SC USING(Sno); 去掉重复值,四、复合条件连接,WHERE子句中含多个连接条件时,称为复合条件连接例37查询选修2号课程且成绩在90分以上的所有学生的学号、姓名 SELECT Student.Sno,
35、 student.Sname FROM Student, SC WHERE Student.Sno = SC.Sno AND /* 连接谓词*/SC.Cno= 2 AND /* 其他限定条件 */SC.Grade 90; /* 其他限定条件 */,六、多表连接,例38 查询每个学生的学号、姓名、选修的课程名及成绩。SELECT Student.Sno,Sname,Cname,GradeFROM Student,SC,CourseWHERE Student.Sno = SC.Sno and SC.Cno = Course.Cno;,3.4.3 嵌套查询,一个SELECT-FROM-WHERE语句
36、称为一个查询块 将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询,SELECT Sname 外层查询/父查询FROM StudentWHERE Sno IN(SELECT Sno 内层查询/子查询FROM SCWHERE Cno= 2 );,子查询的限制 不能使用ORDER BY子句 层层嵌套方式反映了 SQL语言的结构化 有些嵌套查询可以用连接运算替代,嵌套查询分类,不相关子查询 子查询的查询条件不依赖于父查询 相关子查询 子查询的查询条件依赖于父查询,嵌套查询求解方法,不相关子查询 是由里向外逐层处理。即每个子查询在上一级查询处理之前求解,子查询的
37、结果用于建立其父查询的查找条件。 相关子查询 首先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若WHERE子句返回值为真,则取此元组放入结果表; 然后再取外层表的下一个元组; 重复这一过程,直至外层表全部检查完为止。,一、带有IN谓词的子查询,例39 查询与“刘晨”在同一个系学习的学生。, 确定“刘晨”所在系名 SELECT Sdept FROM Student WHERE Sname= 刘晨 ;,此查询要求可以分步来完成,结果为:, 查找所有在IS系学习的学生。 SELECT Sno,Sname,Sdept FROM Student WHERE Sdept= IS
38、;,结果为:,一、带有IN谓词的子查询,例39 查询与“刘晨”在同一个系学习的学生。, 确定“刘晨”所在系名 SELECT Sdept FROM Student WHERE Sname= 刘晨 ;,此查询要求可以分步来完成, 查找所有在IS系学习的学生。 SELECT Sno,Sname,Sdept FROM Student WHERE Sdept= IS ;, 将第一步查询嵌入到第二步查询的条件中。SELECT Sno,Sname,SdeptFROM StudentWHERE Sdept IN(SELECT SdeptFROM StudentWHERE Sname= 刘晨 );,本例为不相关
39、子查询,用自身连接完成本查询要求SELECT S1.Sno,S1.Sname,S1.SdeptFROM Student S1,Student S2WHERE S1.Sdept = S2.Sdept ANDS2.Sname = 刘晨;,父查询和子查询中的表均可以定义别名 SELECT Sno,Sname,SdeptFROM Student S1WHERE S1.Sdept IN(SELECT SdeptFROM Student S2WHERE S2.Sname= 刘晨 );,例40查询选修了课程名为“信息系统”的学生学号和姓名,SELECT Sno,Sname 最后在Student关系中FROM
40、 Student 取出Sno和SnameWHERE Sno IN(SELECT Sno 然后在SC关系中找出选FROM SC 修了3号课程的学生学号WHERE Cno IN(SELECT Cno 首先在Course关系中找出“信FROM Course 息系统”的课程号,结果为3号WHERE Cname= 信息系统);,结果:Sno Sname - 200215121 李勇 200215122 刘晨,用连接查询SELECT Sno,SnameFROM Student,SC,CourseWHERE Student.Sno = SC.Sno ANDSC.Cno = Course.Cno ANDCou
41、rse.Cname=信息系统;,二、带有比较运算符的子查询,当能确切知道内层查询返回单值时,可用比较运算符(,=,)。,例:假设一个学生只可能在一个系学习,并且必须属于一个系,则在例39可以用 = 代替IN :,SELECT Sno,Sname,SdeptFROM StudentWHERE Sdept =SELECT SdeptFROM StudentWHERE Sname= 刘晨 ;,子查询一定要跟在比较符之后错误的例子:SELECT Sno,Sname,SdeptFROM StudentWHERE ( SELECT SdeptFROM StudentWHERE Sname= 刘晨 ) =
42、Sdept;,例41找出每个学生超过他选修课程平均成绩的课程号。SELECT Sno,CnoFROM SC xWHERE Grade=( SELECT AVG(Grade)FROM SC yWHERE y.Sno=x.Sno );,相关子查询,首先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若WHERE子句返回值为真,则取此元组放入结果表; 然后再取外层表的下一个元组; 重复这一过程,直至外层表全部检查完为止。,三、带有ANY或ALL谓词的子查询,谓词语义 ANY:任意一个值 ALL:所有值,三、带有ANY或ALL谓词的子查询,需要配合使用比较运算符, ANY 大于子
43、查询结果中的某个值 ALL 大于子查询结果中的所有值 = ANY 大于等于子查询结果中的某个值 = ALL 大于等于子查询结果中的所有值 )ANY 不等于子查询结果中的某个值 !=(或)ALL 不等于子查询结果中的任何一个值,例42 查询其他系中比计算机科学系任意一个(其中某一个)学生年龄小的学生姓名和年龄SELECT Sname,SageFROM StudentWHERE Sage CS ; /* 注意这是父查询块中的条件 */,查询结果: Sname Sage - 王敏 18 张立 19,执行过程: 1.DBMS执行此查询时,首先处理子查询,找出CS系中所有学生的年龄,构成一个集合(19,
44、20) 2. 处理父查询,找所有不是CS系且年龄小于19 或 20的学生,ANY与ALL与集函数的对应关系,ANY和ALL谓词有时可以用集函数实现,用集函数实现子查询通常比直接用ANY或ALL查询效率要高,因为前者通常能够减少比较次数,例42 :用集函数实现例42 SELECT Sname,SageFROM StudentWHERE Sage CS ;,例43 查询其他系中比计算机科学系所有学生年龄都小的学生姓名及年龄。,查询结果:Sname Sage - 王敏 18,方法二:用集函数SELECT Sname,SageFROM StudentWHERE Sage IS ;,方法一:用ALL谓词
45、SELECT Sname,SageFROM StudentWHERE Sage CS ;,四、带有EXISTS谓词的子查询,1. EXISTS谓词-存在量词 带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。 若内层查询结果非空,则返回真值。 若内层查询结果为空,则返回假值。 由EXISTS引出的子查询,其目标列表达式通常都用* ,因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义 2. NOT EXISTS谓词,例44 查询所有选修了1号课程的学生姓名。,用嵌套查询SELECT SnameFROM StudentWHERE EXIST
46、S(SELECT *FROM SC /*相关子查询*/WHERE Sno=Student.Sno AND Cno= 1);,求解过程的思路分析:本查询涉及Student和SC关系。在Student中依次取每个元组的Sno值,用此值去检查SC关系。若SC中存在这样的元组,其Sno值等于Student.Sno值,并且其Cno= 1,则取此Student.Sname送入结果关系。,用连接运算 SELECT Sname FROM Student, SC WHERE Student.Sno=SC.Sno AND SC.Cno= 1;,相关子查询 相关查询与我们前面的不相关子查询有一个明显区别,即子查询的
47、查询条件依赖于外层父查询的某个属性值(在本例中是依赖于Student表的Sno值),我们称这类查询为相关子查询。 求解相关子查询不能象求解不相关子查询那样,一次将子查询求解出来,然后求解父查询。 相关子查询的内层查询由于与外层查询有关,因此必须反复求值。,例45 查询没有选修1号课程的学生姓名。SELECT SnameFROM StudentWHERE NOT EXISTS(SELECT *FROM SCWHERE Sno = Student.Sno AND Cno=1); 此例用连接运算难于实现,3.不同形式的查询间的替换 一些带EXISTS或NOT EXISTS谓词的子查询不能被其他形式的子查询等价替换 所有带IN谓词、比较运算符、ANY和ALL谓词的子查询都能用带EXISTS谓词的子查询等价替换。,例:例39查询与“刘晨”在同一个系学习的学生。可以用带EXISTS谓词的子查询替换:SELECT Sno,Sname,SdeptFROM Student S1WHERE EXISTSSELECT *FROM Student S2WHERE S2.Sdept = S1.Sdept ANDS2.Sname = 刘晨 ;,