前言
本文内容为我大三上学期数据库原理期末复习时总结的知识点,文章分为三部分:第一部分是手写的知识点总结,第二部分是电子版的简答题总结,第三部分是部分SQL练习题及其解析!
一、知识点总结
二、简答题总结
第1章:绪论
1、数据库是长期储存在计算机内的、有组织的、可共享的、大量数据的集合。
2、数据库系统的三级模式结构
1)模式:也称为逻辑模式,是数据库中全体数据的逻辑结构和特征的描述,所有用户的公共数据视图,综合了所有用户的需求。一个数据库只有一个模式。模式是数据库系统模式结构的中间层,与数据的物理存储细节和硬件环境无关,与具体的应用程序、开发工具及高级程序设计语言无关。
2)外模式:也称子模式或用户模式,是数据库用户(包括应用程序员和最终用户)使用的局部数据的逻辑结构和特征的描述,是数据库用户的数据视图,是与某一应用有关的数据的逻辑表示。外模式介于模式与应用之间。
3)内模式:也也称存储模式,是数据物理结构和存储方式的描述,是数据在数据库内部的表示方式。一个数据库只有一个内模式。
3、三级模式的关系
数据按外模式的描述提供给用户,按内模式的描述存储在磁盘中,而模式则提供了连接这两级的相对稳定的中间观点,并使得两级中任何一级的改变不受另一级的牵制。
4、数据库的二级映像功能
1)外模式/模式映像:模式描述了数据的全局逻辑结构,外模式描述了数据的局部逻辑结构,同一个模式可以有任意多个外模式。每一个外模式,数据库系统都有一个外模式/模式映象,定义外模式与模式之间的对应关系。这些映象定义通常包含在各自外模式的描述中。外模式/模式映象用途:保证数据的逻辑独立性。
2)模式/内模式映像:模式/内模式映象定义了数据全局逻辑结构与存储结构之间的对应关系。例如,说明逻辑记录和字段在内部是如何表示的。数据库中模式/内模式映象是唯一的,该映象定义通常包含在模式描述中。模式/内模式映象的用途:保证数据的物理独立性。
第5章:数据库完整性
1、用户定义在关系表上的一类由事件驱动的特殊过程,一旦定义,任何用户对表的增加、修改和删除工作均由服务器自动激活相应的触发器,在DBMS核心层进行集中的完整性控制。
2、触发器类似于约束,但是比约束更加灵活,可以进行更为复杂的检查和操作,具有更精细和更强大的数据控制能力。为实现动态约束以及多个元组之间的完整性约束,就需要触发器技术Trigger。
Trigger是一种过程完整性约束(相比之下,CreateTable中定义的都是非过程性约束),是一段程序,该程序可以在特定的时刻被自动触发执行,比如在一次更新操作之前执行,或在更新操作之后执行。
3、触发器经常用于加强数据的完整性约束和业务规则等。触发器创建语法四要素:监视地点(table)、监视事件(insert/update/delete)、触发时间(after/before)、触发事件(insert/update/delete)。
4、触发器的创建者:表的拥有者,即表的创建者;触发器名:同一模式下是唯一的;表名:触发器的目标表;触发事件:INSERT、DELETE、UPDATE,也可以是这些操作的组合。
第7章:数据库设计
1、按规范设计法可将数据库设计分为六个阶段:系统需求分析阶段、概念结构设计阶段、逻辑结构设计阶段、物理设计阶段、数据库实施阶段、数据库运行与维护阶段。
2、数据字典的用途:数据字典是各类数据描述的集合,是进行详细的数据收集和数据分析所获得的主要结果。数据字典在数据库设计中占有很重要的地位。
第10章:数据库恢复技术
1、日志文件与静态转储后备副本配合进行介质故障恢复
静态转储的数据已是一致性的数据。出现介质故障后,1)重装后备副本,恢复到转储结束时的一致性状态2)利用日志文件把已完成的事务重做,对故障发生时尚未完成的事务撤销处理。
2、日志文件与动态转储后备副本配合进行介质故障恢复
动态转储数据库的同时,转储同一时点的日志文件,后备副本与该日志文件结合起来才能将数据库恢复到一致性状态。利用这些日志文件副本进一步恢复事务,避免重新运行事务程序。
3、事务故障的恢复方法与步骤
恢复方法:由恢复子系统利用日志文件撤销(undo)此事务已经对数据库进行的修改,该恢复由系统自动完成,不需要用户干预。
恢复步骤:
1)反向扫描文件日志,查找该事务的更新操作。
2)对该事务的更新操作执行逆操作。即将日志记录中“更新前的值”写入数据库。具体分为:
插入操作:“更新前的值”为空,则做删除操作。删除操作:“新后的值”为空,则做插入操作。修改操作:则用修改前的值代替修改后的值。
3)继续反向扫描日志文件,查找该事务的其他更新操作,并做同样处理。如此处理下去,直至读到此事务的开始标记,事务故障恢复就完成了。
4、系统故障的恢复方法与步骤
系统故障造成数据库不一致状态的原因是:一些未完成事务对数据库的更新已写入数据库;一些已提交事务对数据库的更新还留在缓冲区没来得及写入数据库。
恢复方法:撤销(undo)故障发生时未完成的事务,重做(redo)已完成的事务。
恢复步骤:
1)正向扫描日志文件(即从头扫描日志文件)找到故障发生前已经提交的事务,将其事务标识记入“重做队列”,同时找到故障发生时尚未完成的事务,将其事务表示记入“撤销队列”。
2)反向扫描日志文件,对每个UNDO事务的更新操作执行逆操作,即将“更新前的值”写入数据库。
3)正向扫描日志文件,对Redo队列事务进行REDO处理,即对每个REDO事务重新执行日志文件登记的操作。
4、介质故障的恢复方法与步骤
恢复方法:重装数据库,使数据库恢复到一致性状态,然后重做(REDO)已完成的事务。
恢复步骤:
1)装入最新的数据库后备副本,使数据库恢复到最近一次转储是的一致性状态。对于动态转储的后备副本,还需同时装入自转储开始时刻的日志文件副本,利用恢复系统故障的方法(redo undo),才能使得数据库恢复到一致性状态。
2)装入相应的日志文件副本(转储结束时刻的日志文件副本),重做已经完成的事务。首先扫描日志文件,找出故障发生时已提交的事务的标识,将其记入重做队列。然后正向扫描日志文件,对重做队列中的所有事务进行重做处理。即将日志记录中“更新后的值”写入数据库。
5、动态维护日志文件
方法:周期性地执行建立检查点、保存数据库状态的操作。即:
1)将当前日志缓冲区中的所有日志记录写入磁盘的日志文件上。2)在日志文件中写入一个检查点记录。3)将当前数据缓冲区的所有数据记录写入磁盘的数据库中。4)把检查点记录在日志文件中的地址写入一个重新开始文件。定期:按照预定的一个时间间隔。不定期:按照某种规则,如日志文件已写满一半建立一个检查点。
5、利用检查点方法进行恢复步骤
1)从重新开始文件中找到最后一个检查点记录在日志文件中的地址,由该地址在日志文件中找到最后一个检查点记录。
2)由该检查点记录得到检查点建立时刻所有正在执行的事务清单ACTIVE-LIST,建立两个事务队列:UNDO-LIST和REDO-LIST。把ACTIVE-LIST暂时放入UNDO-LIST队列,REDO队列暂为空。
3)从检查点开始正向扫描日志文件,直到日志文件结束。如有新开始的事务Ti,把Ti暂时放入UNDO-LIST队列。如有提交的事务Tj,把Tj从UNDO-LIST队列移到REDO-LIST队列。
4)对UNDO-LIST中的每个事务执行UNDO操作,对REDO-LIST中的每个事务执行REDO操作。
5、数据库镜像的作用
DBMS自动把整个数据库或其中的关键数据复制到另一个磁盘上,DBMS自动保证镜像数据与主数据的一致性。
作用:
1)出现介质故障时:DBMS自动利用镜像磁盘数据进行数据库的恢复,不需要关闭系统和重装数据库副本。
2)没有出现故障时:可用于并发操作,即当一个用户对数据加排他锁修改数据时,其他用户可以读镜像数据库上的数据。
第11章:并发控制
三级封锁协议与两段锁协议的区别:
1、过程不同:三级封锁协议是一步完成封锁的,而后者却要分为两个阶段,耗费时间。
2、含义不同:两段锁协议是指每个事务的执行可以分为两个阶段:生长阶段(加锁阶段)和衰退阶段(解锁阶段),三级加锁协议也称为三级封锁协议,是为了保证正确的调度事务的并发操作,事务在对数据库对象加锁,解锁是必须遵守的一种规则.在运用X锁和S锁对数据对象加锁时,还需要约定一些规则。
3、功能不同:三级封锁协议除防止了丢失修改和不读“脏”数据外,还进一步防止了不可重复读。后者只是对事务进行时的封锁。
补充
1、数据库系统主要特点:数据结构化(主要特征,与文件本质区别)、数据共享性高冗余度低且易扩充、数据独立性高、数据由数据库管理系统统一管理和控制。
2、外模式/模式映象用途:保证数据的逻辑独立性
当模式改变时(增加新的关系、新的属性、改变属性的数据类型等),数据库管理员修改有关的外模式/模式映象,可以使外模式保持不变;应用程序是依据数据的外模式编写的,从而应用程序不必修改,保证了数据与程序的逻辑独立性,简称数据的逻辑独立性。
3、模式/内模式映象的用途:保证数据的物理独立性当数据库的存储结构改变了(例如选用了另一种存储结构),数据库管理员修改模式/内模式映象,使模式保持不变;应用程序不受影响,保证了数据与程序的物理独立性,简称数据的物理独立性。
4、相对于非关系模型,关系数据模型的缺点之一是存取路径对用户透明,需进行查询优化。
5、视图是从一个或几个基本表导出的表,它与基本表不同,它是一个虚表,数据库中只存放视图的定义,而不存放视图对应的数据,这些数据存放在原来的基本表中,当基本表中的数据发生变化,从视图中查询出的数据也就随之改变。视图一经定义就可以像基本表一样被查询、删除,也可以在一个视图之上再定义新的视图,但是对视图的更新操作有限制。
6、数据模型是严格定义的概念的集合,通常由三部分组成:数据结构(描述系统的静态特性)、数据操作(描述系统的动态特性)、完整性约束(描述系统中数据的制约和依存规则)。
1)数据结构描述了系统的静态特性数据结构描述了数据库的组成对象以及对象间的联系,是刻画一个数据模型性质最重要的方面。在数据库系统中,人们通常按照其数据结构的类型来命名数据模型。例如:层次结构、网状结构和关系结构的数据模型,被分别命名为层次模型、网状模型和关系模型。
2)数据操作描述了系统的动态特性数据操作是对DB中各种对象(型)和实例(值)所允许进行的操作以及操作规则的集合。DB主要包括查询和更新(包括插入、修改和删除)两大类操作。数据模型必须定义这些操作的确切含义、操作符号、操作规则以及实现操作的语言。
3)完整性约束是一组完整性规则完整性规则是给定的数据模型中数据及其联系所具有的制约和依存规则集合,用以限定符合数据模型的DB状态及其变化,以保证数据的正确性、有效性和相容性。数据模型应该反映和规定本数据模型必须遵守的基本的通用的完整性约束条件。
7、参照完整性规则:若属性(或属性组)F是基本关系R的外码,它与基本关系S的主码Ks相对应(基本关系R和S不一定是不同的关系),则对于R中每个元组在F上的值必须为:取空值(F的每个属性值均为空值)或者等于S中某个元祖的主码值。
8、实体完整性规则:若属性A是基本关系R的主属性,则属性A不能取空值。基本关系的所有主属性不能取空值,而不仅是主码整体不能取空值。
1)实体完整性规则是针对基本关系而言的。一个基本表通常对应现实世界的一个实体集或一个多对多联系。例如:“学生”关系对应学生实体,“选课”关系对应学生和选修课程之间的多对多联系。2)现实世界中的实体是可区分的,即它们具有某种唯一性标识。例如,每个学生都是可以区分的独立的个体。相应地,关系模型中以主码作为唯一性标识。3)主码中的属性(即主属性)不能取空值。空值就是“不知道”或“无意义”的值。如果主属性取空值,就说明存在某个不可标识的实体,即存在不可区分的实体,这与上一点相矛盾,因此这个规则称为实体完整性。
9、实体完整性检查
用PRIMARY KEY定义了关系的主码之后,每当对基本表插入记录或对码列进行更新操作时,RDBMS按照实体完整性规则自动进行检查。包括:
1)检查主码值是否唯一,如果不唯一则拒绝插入或修改。
2)检查主码的各个属性是否为空,只要有一个为空就拒绝插入或修改。
10、参照完整性检查
1)当参照表中进行插入或者修改外码值操作时,可能破坏被参照表中参照完整性,这时拒绝操作。
2)当被参照表中删除元祖或者修改主码值时,可能破坏参照表中的参照完整性,这时可作出以下处理:拒绝操作(no action)、级联(cascade)删除(修改)、或者设置成空值。
11、数据库设计的六个阶段概述
1)需求分析阶段:需求分析是整个数据库设计过程的基础,要收集数据库所有用户的信息内容和处理要求,并加以规格化和分析。这是最费时、最复杂的一步,但也是最重要的一步,相当于待构建的数据库大厦的地基,它决定了以后各步设计的速度与质量。需求分析做得不好,可能会导致整个数据库设计返工重做。
2)概念结构设计阶段:是整个数据库设计的关键,它通过对用户需求进行综合、归纳与抽象,形成一个独立于具体数据库管理系统的概念模型。
3)逻辑结构设计阶段:将概念结构转换为某个数据库管理系统所支持的数据模型,并对其进行优化。
4)物理结构设计阶段:为逻辑数据模型选取一个最适合应用环境的物理结构,包括存储结构和存取方法。
5)数据库实施阶段:在该阶段,设计人员运用DBMS提供的数据库语言及其宿主语言,根据逻辑设计与物理设计的结果建立数据库,编写相应程序,并进行试运行。
6)数据库运行和维护阶段:在数据库经过试运行后即可投入正式运行。在数据库系统运行过程中必须不断地对其进行评估、调整与修改。
三、SQL练习题及解析
设教学数据库Education有三个关系:
学生关系S(SNO,SNAME,AGE,SEX,SDEPT);学习关系SC(SNO,CNO,GRADE);课程关系C(CNO,CNAME,CDEPT,TNAME)
查询问题:
(1)检索计算机系的全体学生的学号,姓名和性别;
(2)检索学习课程号为C2的学生学号与姓名;
(3)检索选修课程名为“DS”的学生学号与姓名;
(4)检索选修课程号为C2或C4的学生学号;
(5)检索至少选修课程号为C2和C4的学生学号;
(6)检索不学C2课的学生姓名和年龄;
(7)检索学习全部课程的学生姓名;
(8)查询所学课程包含学生S3所学课程的学生学号。
解析:
(1)检索计算机系的全体学生的学号,姓名和性别;
SELECT Sno,Sname,Sex
FROM S
WHERE Sdept =’CS’;
(2)检索学习课程号为C2的学生学号与姓名;
(3)检索选修课程名为“DS”的学生学号与姓名
SELECT Sno,Sname
FROM S
WHERE Sno IN
(SELECT Sno
FROM SC
WHERE Cno IN
(SELECT Cno
FROM C WHERE Cname=‘DS’));
(4)检索选修课程号为C2或C4的学生学号;
SELECT Sno
FROM SC
WHERE Cno=‘C2’ OR Cno=‘C4’;
(5)检索至少选修课程号为C2和C4的学生学号;
SELECT Sno
FROM SC X,SC Y
WHERE X.Sno=Y.Sno AND X.Cno=‘C2’ AND Y.Cno=‘C4’ ;
(6)检索不学C2课的学生姓名和年龄;
(7)检索学习全部课程的学生姓名;
SELECT Sname
FROM S
WHERE NOT EXISTS
(SELECT *
FROM C
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE SC.Sno=S.Sno AND SC.Cno=C.Cno));
(8)查询所学课程包含学生S3所学课程的学生学号。
SELECT DISTINCT Sno
FROM SC AS X
WHERE NOT EXISTS
(SELECT *
FROM SC AS Y
WHERE Y.Sno=‘S3’ AND NOT EXISTS
(SELECT *
FROM SC AS Z
WHERE Z.Sno=X.Sno AND Z.Cno=Y.Cno));
第二部分
设教学数据库Education有三个关系:
学生关系S(SNO,SNAME,AGE,SEX,SDEPT);
学习关系SC(SNO,CNO,GRADE);
课程关系C(CNO,CNAME,CDEPT,TNAME)
查询问题:
1:查所有年龄在20岁以下的学生姓名及年龄。
2:查考试成绩有不及格的学生的学号
3:查所年龄在20至23岁之间的学生姓名、系别及年龄。
4:查计算机系、数学系、信息系的学生姓名、性别。
5:查既不是计算机系、数学系、又不是信息系的学生姓名、性别
6:查所有姓“刘”的学生的姓名、学号和性别。
7:查姓“上官”且全名为3个汉字的学生姓名。
8:查所有不姓“张”的学生的姓名。
9:查DB_Design课程的课程号。
10:查缺考的学生的学号和课程号。
11:查年龄为空值的学生的学号和姓名。
12:查计算机系20岁以下的学生的学号和姓名。
13:查计算机系、数学系、信息系的学生姓名、性别。
14:查询选修了C3课程的学生的学号和成绩,其结果按分数的降序排列。
15:查询全体学生的情况,查询结果按所在系升序排列,对同一系中的学生按年龄降序排列。
16:查询学生总人数。
17:查询选修了课程的学生人数。
18:计算选修了C1课程的学生平均成绩。
19:查询学习C3课程的学生最高分数。
20:查询各个课程号与相应的选课人数。
21:查询计算机系选修了3门以上课程的学生的学号。
22:求基本表S中男同学的每一年龄组(超过50人)有多少人?要求查询结果按人数升序排列,人数相同按年龄降序排列。
23:查询每个学生及其选修课程的情况。
24:查询选修了C2课程且成绩在90分以上的所有学生。
25:查询每个学生选修的课程名及其成绩。
26:统计每一年龄选修课程的学生人数。
27:查询选修了C2课程的学生姓名。
28:查询与“张三”在同一个系学习的学生学号、姓名和系别。
29:查询选修课程名为“数据库”的学生学号和姓名。
30:查询与“张三”在同一个系学习的学生学号、姓名和系别。
31:查询选修课程名为“数据库”的学生学号和姓名。
32:查询选修了C2课程的学生姓名。
33:查询所有未选修C2课程的学生姓名。
34:查询与“张三”在同一个系学习的学生学号、姓名和系别。
35:查询选修了全部课程的学生姓名。
36:查询所学课程包含学生S3所学课程的学生学号
(1)比较
例1:查所有年龄在20岁以下的学生姓名及年龄。
SELECT Sname,Sage
FROM S
WHERE Sage<20; (NOT age>=20)
例2:查考试成绩有不及格的学生的学号
SELECT DISTINCT Sno
FROM SC
WHERE grade<60;
(2)确定范围
例3:查所年龄在20至23岁之间的学生姓名、系别及年龄。
SELECT Sname,Sdept,Sage
FROM S
WHERE Sage BETWEEN 20 AND 23;
(3)确定集合
例4:查计算机系、数学系、信息系的学生姓名、性别。
SELECT Sname,Ssex
FROM S
WHERE Sdept IN (’CS’, ‘IS’, ‘MATH’);
例5:查既不是计算机系、数学系、又不是信息系的学生姓名、性别
SELECT Sname,Ssex
FROM S
WHERE Sdept NOT IN (’CS’, ‘IS’, ‘MATH’);
(4)字符匹配
例6:查所有姓“刘”的学生的姓名、学号和性别。
SELECT Sname,Sno,Ssex
FROM S
WHERE Sname LIKE ‘刘%’;
例7:查姓“上官”且全名为3个汉字的学生姓名。
SELECT Sname
FROM S
WHERE Sname LIKE ‘上官_ _’;
例8:查所有不姓“张”的学生的姓名。
SELECT Sname,Sno,Ssex
FROM S
WHERE Sname NOT LIKE ‘张%’;
例9:查DB_Design课程的课程号。
SELECT Cno
FROM C
WHERE Cname LIKE ‘DB_Design’ ESCAPE ‘’;
(5)涉及空值的查询
例10:查缺考的学生的学号和课程号。
SELECT Sno,Cno
FROM SC
WHERE Grade IS NULL; (不能用=代替)
{ 有成绩的 WHERE Grade IS NOT NULLL;}
例11:查年龄为空值的学生的学号和姓名。
SELECT Sno,Sname
FROM S
WHERE Sage IS NULL;
(6)多重条件查询
例12:查计算机系20岁以下的学生的学号和姓名。
SELECT Sno,Sname
FROM S
WHERE Sdept=‘CS’ AND Sage<20;
例13:查计算机系、数学系、信息系的学生姓名、性别。
SELECT Sname,Ssex
FROM S
WHERE Sdept =’CS’ OR Sdept =‘IS’ OR Sdept =’MATH’);
(7)对查询结果排序
例14:查询选修了C3课程的学生的学号和成绩,其结果按分数的降序排列。
SELECT Sno,Grade
FROM SC
WHERE Cno=‘C3’
ORDER BY Grade DESC;
例15:查询全体学生的情况,查询结果按所在系升序排列,对同一系中的学生按年龄降序排列。
SELECT *
FROM S
ORDER BY Sdep,Sage DESC;
(8)聚合函数的使用
例16:查询学生总人数。
SELECT COUNT(*)
FROM S
例17:查询选修了课程的学生人数。
SELECT COUNT(DISTINCT Sno)
FROM SC
例18:计算选修了C1课程的学生平均成绩。
SELECT AVG(Grade)
FROM SC
WHERE Cno=‘C1’;
例19:查询学习C3课程的学生最高分数。
SELECT MAX(Grade)
FROM SC
WHERE Cno=‘C3’;
(9)对查询结果分组
例20:查询各个课程号与相应的选课人数。
SELECT Cno,COUNT(Sno)
FROM SC
GROUP BY Cno;
该SELECT语句对SC表按Cno的取值进行分组,所有具有相同Cno值的元组为一组,然后对每一组作用聚合函数COUNT以求得该组的学生人数。
如果分组后还要求按一定的条件对这些组进行筛选,最终只输出满足指定条件 组,则可以使用HAVING短语指定筛选条件。
例21:查询计算机系选修了3门以上课程的学生的学号。
SELECT Sno
FROM SC
WHERE Sdept=‘CS’
GROUP BY Sno
HAVING COUNT(*)>3;
WHERE子句与HAVING短语的根本区别在于作用对象不同。WHERE子句作用于基本表或视图,从中选择满足条件的元组。HAVING短语作用于组,从中选择满足条件的组。
例22:求基本表S中男同学的每一年龄组(超过50人)有多少人?要求查询结果按人数升序排列,人数相同按年龄降序排列。
SELECT Sage,COUNT(Sno)
FROM S
WHERE Ssex='M'
GROUP BY Sage
HAVING COUNT(*)> 50
ORDER BY 2,Sage DESC;
联接查询
例23:查询每个学生及其选修课程的情况。
SELECT S.Sno,Sname,Sage,Ssex,Sdept,Cno,Grade
FROM S, SC
WHERE S.Sno=SC.Sno;
例24:查询选修了C2课程且成绩在90分以上的所有学生。
SELECT S.Sno,Sname
FROM S,SC
WHERE S.Sno=SC.Sno
AND SC.Cno=‘C2’
AND SC.Grade > 90;
例25:查询每个学生选修的课程名及其成绩。
SELECT S.Sno,Sname,Cname,SC.Grade
FROM S,SC,C
WHERE S.Sno=SC.Sno AND SC.Cno=C.Cno
例26:统计每一年龄选修课程的学生人数。
SELECT Sage,COUNT(DISTINCT S.Sno)
FROM S,SC
WHERE S.Sno=SC.Sno
GROUP BY S;
由于要统计每一个年龄的学生人数,因此要把满足WHERE子句中条件的查询结果按年龄分组,在每一组中的学生年龄相同。此时的SELECT子句应对每一组分开进行操作,在每一组中,年龄只有一个值,统计的人数是这一组中的学生人数。
嵌套查询
(1)带有IN谓词的子查询
指父查询与子查询之间用IN进行联接,判断某个属性列值是否在子查询的结果中。
例27:查询选修了C2课程的学生姓名。
SELECT Sname
FROM S
WHERE Sno IN
( SELECT Sno
FROM SC
WHERE Cno=‘C2’);
例28:查询与“张三”在同一个系学习的学生学号、
姓名和系别。
分析:
(1)确定“张三”所在的系;
(2)查找所有在X系学习的学生。
SELECT Sdept
FROM S
WHERE Sname=‘张三’;
SELECT Sno,Sname,Sdept
FROM S
WHERE Sdept=‘X’
把第一步查询嵌入到第二步查询中,用以构造第二步查询的条件。
SELECT Sno,Sname,Sdept
FROM S
WHERE Sdept IN
(SELECT Sdept
FROM S
WHERE Sname=‘张三’);
例29:查询选修课程名为“数据库”的学生学号和姓名。
本查询涉及到学号、姓名和课程名三个属性,分别存放在S和C表中,但S和C表没有直接联系,必须通过SC表建立它们二者的联系。 C → SC → S
基本思路:
(1)首先在C表中找出“DB”课程的课程号Cno;
(2)然后在SC表中找出Cno等于第一步给出的Cno 集合中的某个元素Cno;
(3)最后在S关系中选出Sno等于第二步中Sno 集合中某个元素的元组,取出Sno 和Sname送入结果表列。
SELECT Sno,Sname
FROM S
WHERE Sno IN
(SELECT Sno
FROM SC
WHERE Cno IN
(SELECT Cno
FROM C
WHERE Cname=‘DB’));
带有比较运算符的子查询
例30:查询与“张三”在同一个系学习的学生学号、
姓名和系别。
SELECT Sno,Sname,Sdept
FROM S
WHERE Sdept =
(SELECT Sdept
FROM S
WHERE Sname=‘张三’);
例31:查询选修课程名为“数据库”的学生学号和姓名。
SELECT Sno,Sname
FROM S
WHERE Sno IN
(SELECT Sno
FROM SC
WHERE Cno =
(SELECT Cno
FROM C
WHERE Cname=‘DB’));
(3)带有EXISTS谓词的子查询
(1)带有EXISTS谓词的子查询不返回任何实际数据,它只产生逻辑值。
例32:查询选修了C2课程的学生姓名。
1.SELECT Sname
FROM S
WHERE Sno IN
( SELECT Sno
FROM SC
WHERE Cno=‘C2’);
2.SELECT Sname
FROM S
WHERE EXISTS
( SELECT *
FROM SC
WHERE SC.Sno=S.Sno AND Cno=‘C2’);
例33:查询所有未选修C2课程的学生姓名。
SELECT Sname
FROM S
WHERE NOT EXISTS
( SELECT *
FROM SC
WHERE SC.Sno=S.Sno AND Cno=‘C2’);
[NOT]EXISTS 实际上是一种内、外层互相关的嵌套查询,只有当内层引用了外层的值,这种查询才有意义。
例34:查询与“张三”在同一个系学习的学生学号、
姓名和系别。
SELECT Sno,Sname,Sdept
FROM S AS S1
WHERE EXISTS
(SELECT *
FROM S AS S2
WHERE S2.Sdept=S1. Sdept AND S2.Sname=‘张三’);
相关子查询
例35:查询选修了全部课程的学生姓名。
在表S中找学生,要求这个学生学了全部课程。换言之,在S表中找学生,在C中不存在一门课程,这个学生没有学。
SELECT Sname
FROM S
WHERE NOT EXISTS
(SELECT *
FROM C
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE SC.Sno=S.Sno AND SC.Cno=C.Cno));
例36:查询所学课程包含学生S3所学课程的学生学号
分析:不存在这样的课程Y,学生S3选了Y,而其他学生没有选。
SELECT DISTINCT Sno
FROM SC AS X
WHERE NOT EXISTS
(SELECT *
FROM SC AS Y
WHERE Y.Sno=‘S3’ AND NOT EXISTS
(SELECT *
FROM SC AS Z
WHERE Z.Sno=X.Sno AND Z.Cno=Y.Cno));