2023年6月21日发(作者:)
实验4 SQL语言——SELECT查询操作
实实验验44
SSQQLL语语言言————SSEELLEECCTT查查询询操操作作
实验示例
实验示例中要使用包括如下三个表的“教学管理”数据库JXGL:
(1)学生表Student,由学号(Sno)、姓名(Sname)、性别(Ssex)、年龄(Sage)、所在系(Sdept)五个属性组成,记作:Student(Sno,Sname,Ssex,Sage,Sdept),其中主码为Sno。
(2)课程表Course,由课程号(Cno)、课程名(Cname)、先修课号(Cpno)、学分(Ccredit)四个属性组成,记作:Course(Cno,Cname,Cpno,Ccredit),其中主码为Cno。
(3)学生选课SC,由学号(Sno)、课程号(Cno)、成绩(Grade)三个属性组成,记作:SC(Sno,Cno,Grade),其中主码为(SNO,CNO)。
1、在SQL SERVER查询分析器或企业管理器(以具有相应操作权限的某用户登录)的SQL操作窗口中执行如下命令创建数据库。需要说明的是不同数据库系统其创建数据库的命令或方式有所不同。
CREATE DATABASE JXGL
2、刷新数据库目录后,选择新出现的JXGL数据库,在SQL操作窗口中,创建Student、SC、Course三表及表记录插入命令如下:
Create Table Student
( Sno CHAR(5) NOT NULL PRIMARY KEY(Sno),
Sname VARCHAR(20),
Sage SMALLINT CHECK(Sage>=15 AND Sage<=45),
Ssex CHAR(2) DEFAULT '男' CHECK (Ssex='男' OR Ssex='女'),
Sdept CHAR(2));
Create Table Course
( Cno CHAR(2) NOT NULL PRIMARY KEY(Cno),
Cname VARCHAR(20),
Cpno CHAR(2),
Ccredit SMALLINT);
Create Table SC
( Sno CHAR(5) NOT NULL CONSTRAINT S_F FOREIGN KEY REFERENCES Student(Sno),
Cno CHAR(2) NOT NULL,
Grade SMALLINT CHECK ((Grade IS NULL) OR (Grade BETWEEN 0 AND 100)),
PRIMARY KEY(Sno,Cno),
1 数据库原理与应用实验指导
FOREIGN KEY(Cno) REFERENCES Course(Cno));
INSERT INTO Student VALUES('98001','钱横',18,'男','CS');
INSERT INTO Student VALUES('98002','王林',19,'女','CS');
INSERT INTO Student VALUES('98003','李民',20,'男','IS');
INSERT INTO Student VALUES('98004','赵三',16,'女','MA');
INSERT INTO Course VALUES('1','数据库系统', '5',4);
INSERT INTO Course VALUES('2','数学分析',null ,2);
INSERT INTO Course VALUES('3','信息系统导论','1',3);
INSERT INTO Course VALUES('4','操作系统原理','6',3);
INSERT INTO Course VALUES('5','数据结构','7',4);
INSERT INTO Course VALUES('6','数据处理基础',null,4);
INSERT INTO Course VALUES('7','C语言','6',3);
INSERT INTO SC VALUES('98001','1',87);
INSERT INTO SC VALUES('98001','2',67);
INSERT INTO SC VALUES('98001','3',90);
INSERT INTO SC VALUES('98002','2',95);
INSERT INTO SC VALUES('98002','3',88);
[例1] 查考试成绩大于等于90的学生的学号。
SELECT DISTINCT Sno
FROM SC
WHERE Grade>=90;
这里使用了DISTINCT短语,当一个学生有多门课程成绩大于等于90时,他的学号也只列一次。执行结果如图4-1所示。
图4-1 在查询分析器中的查询执行情况
[例2] 查年龄大于18,并不是信息系(IS)与数学系(MA)的学生的姓名和性别。
SELECT Sname,Ssex
FROM Student
WHERE Sage>18 AND Sdept NOT IN ('IS', 'MA');
在企业管理器中的执行情况如图4-2所示。
图4-2 在企业管理器中的查询执行情况
[说明](1)在企业管理器中打开子窗口的方法:先选中数据库→选中表→在任一表上,按鼠标右键→从快捷菜单中选择“打开表”→点击“返回所有行”子菜单项→在打开返回表内容的子窗口后,按企业管理器工具栏上的“SQL”图标,即能把子窗口分为上下两部分,上面部分能输入不同的SQL命令来执行,执行时按企业管理器工具栏上的“运行”图标
即可;(2)限于篇幅,其它查询命令的执行窗口与运行情况类似于上两图,原则将
2 实验4 SQL语言——SELECT查询操作
不再列出。
[例3] 查以”MIS_”开头,且倒数第二个汉字为“导”字的课程的详细情况。
SELECT * FROM Course
WHERE Cname LIKE ’MIS#_%导_’ ESCAPE ’#’;
[例4] 查询选修了课程的学生人数。
SELECT COUNT(DISTINCT Sno) /* 加DISTINCT 去掉重复值后计数 */
FROM SC;
[例5] 查询计算机系(CS)选修了2门及以上课程的学生的学号。
SELECT
FROM Student,SC
WHERE Sdept='CS' AND =
GROUP BY HAVING COUNT(*)>=2;
[例6] 查询Student表与SC表的广义笛卡尔积。
Select Student.*,SC.*
From Student,SC;
或 Select Student.*,SC.*
From Student Cross Join SC;
[例7] 查询Student表与SC表基于学号SNO的等值连接。
Select *
From Student,SC
WHERE =;
[例8] 查询Student表与SC表基于学号SNO的自然连接。
SELECT , Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student, SC WHERE =;
或 SELECT , Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student INNER JOIN SC ON =;
[例9] 查询课程之先修课的先修课(自身连接例)。
SELECT ,
FROM Course FIRST, Course SECOND
WHERE =;
我们为Course表取两个别名FIRST与SECOND,这样就可以在SELECT子句和WHERE子句中的属性名前分别用这两个别名加以区分。
[例10] 查询学生及其课程、成绩等情况(不管是否选课,均需列出学生信息)。
SELECT , Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student Left Outer JOIN SC ON =;
3 数据库原理与应用实验指导
[例11] 查询学生及其课程成绩与课程及其学生选修成绩的明细情况(要求学生与课程均需全部列出)。
SELECT , Sname, Ssex, Sage, Sdept, , Grade, cname, cpno,
ccredit
FROM Student Left Outer JOIN SC ON = Full Outer join Course
on =;
[例12] 查询性别为男、课程成绩及格的学生信息及课程号、成绩。
SELECT Student.*,Cno,Grade
FROM STUDENT INNER JOIN ON =
WHERE SSEX=’男’ AND GRADE >=60
[例13] 查询与“钱横”在同一个系学习的学生信息。
SELECT * FROM Student
WHERE Sdept IN
(SELECT Sdept
FROM Student
WHERE Sname='钱横');
或 SELECT * FROM Student
WHERE Sdept =
( SELECT Sdept
FROM Student
WHERE Sname='钱横'); -- 当子查询为单列单行值时可以用“=”
或 SELECT S1.*
FROM Student S1,Student S2
WHERE = AND ='钱横';
一般来说,连接查询可以替换大多数的嵌套子查询。
SQL-92支持“多列成员”的属于(IN)条件表达,例:
[例14] 找出同系、同年龄、同性别的学生。
Select * from Student as T
Where (,,) IN
(Select sdept,sage,ssex
From student as S
Where <>); -- SQL Server 2000可能不支持
它等价于逐个成员IN的方式表达,如下(能在SQL Server 2000中执行):
Select * from Student T
Where IN
( Select sdept
From student S
Where <> and
IN
( Select sage
4 实验4 SQL语言——SELECT查询操作
From student X
Where = and <> and
IN
( Select ssex
From student Y
Where = and <>)));
[例15] 查询选修了课程名为“数据库系统”的学生学号、姓名和所在系。
SELECT Sno,Sname,Sdept FROM Student -- IN嵌套查询方法
WHERE Sno IN
( SELECT Sno FROM SC
WHERE Cno IN
( SELECT Cno FROM Course WHERE Cname='数据库系统'));
或 SELECT Sno,Sname,Sdept FROM Student -- IN、= 嵌套查询方法
WHERE Sno IN
( SELECT Sno FROM SC
WHERE Cno=
( SELECT Cno FROM Course WHERE Cname='数据库系统'));
或 SELECT ,Sname,Sdept --连接查询方法
FROM Student,SC,Course
WHERE = AND =
AND ='数据库系统';
或 Select Sno,Sname,Sdept From Student -- Exists嵌套查询方法
Where Exists( Select * From SC
Where = And
Exists( Select * From Course
Where = And Cname='数据库系统'));
或 Select Sno,Sname,Sdept From Student -- Exists嵌套查询方法
Where Exists( Select * From course
Where Cname='数据库系统' and
Exists( Select * From SC
Where = and = ));
[例16] 检索至少不学2和4两门课程的学生学号与姓名。
SELECT Sno,Sname FROM Student
WHERE Sno NOT IN
(SELECT Sno FROM SC WHERE Cno IN ('2','4'));
[例17] 查询其他系中比信息系IS所有学生年龄均大的学生名单,并排序输出。
SELECT Sname FROM Student
WHERE Sage>All(SELECT Sage FROM Student
WHERE Sdept='IS') AND Sdept <> 'IS'
ORDER BY Sname;
本查询实际上也可以用集函数实现:
5 数据库原理与应用实验指导
SELECT Sname FROM Student
WHERE Sage>(SELECT MAX(Sage) FROM Student
WHERE Sdept='IS') AND Sdept<>'IS'
ORDER BY Sname;
[例18] 查询哪些课程只有女生选读。(本题有多于两种表达法)
SELECT DISTINCT CNAME
FROM COURSE C
WHERE '女'=ALL( SELECT SSEX FROM SC,STUDENT
WHERE = AND =);
或 SELECT DISTINCT CNAME FROM COURSE C
WHERE NOT EXISTS
( SELECT * FROM SC,STUDENT
WHERE = AND = AND ='男');
[例19] 查询所有未修1号课程的学生姓名。
SELECT Sname FROM Student
WHERE NOT EXISTS
( SELECT * FROM SC WHERE Sno= AND Cno='1');
或 SELECT Sname FROM Student
WHERE Sno NOT IN (SELECT Sno FROM SC WHERE Cno='1');
但如下是错的:
SELECT Sname FROM Student,SC
WHERE = AND Cno<>'1';
[例20] 查询选修了全部课程的学生姓名(为了有查询结果,自己可调整一些表的)。
SELECT Sname FROM Student
WHERE NOT EXISTS
( SELECT * FROM Course
WHERE NOT EXISTS
(SELECT * FROM SC WHERE Sno= AND Cno=));
由于没有全称量词,我们将题目的意思转换成等价的存在量词的形式:查询这样的学生姓名没有一门课程是他不选的。
本题的另一操作方法是:
SELECT Sname FROM Student,SC WHERE =
Group by ,Sname having count(*)>=(SELECT count(*) FROM Course);
[例21] 查询至少选修了学生98001选修的全部课程的学生号码。
本题的查询要求可以做如下解释,不存在这样的课程y,学生98001选修了y,而要查询的学生x没有选。写成的SELECT语句为:
SELECT Sno
FROM Student SX
WHERE NOT EXISTS
6 实验4 SQL语言——SELECT查询操作
( SELECT * FROM SC SCY
WHERE ='98001' AND
NOT EXISTS
( SELECT * FROM SC SCZ
WHERE = AND =));
[例22] 查询选修了课程1或者选修了课程2的学生学号集。
SELECT Sno FROM SC WHERE Cno='1'
UNION
SELECT Sno FROM SC WHERE Cno='2';
[注意] 扩展的SQL中有集合操作并(UNION)、集合操作交(INTERSECT)和集合操作差(EXCEPT或MINUS)等。SQL的集合操作要求相容即属性个数、类型必须一致,属性名无关,最终结果集采用第一个结果的属性名,缺省为自动去除重复元组,各子查询不带Order By,Order By放在整个语句的最后。
[例23] 查询计算机科学系的学生与年龄不大于19岁的学生的交集。
SELECT * FROM Student WHERE Sdept='CS'
INTERSECT
SELECT * FROM Student WHERE Sage<=19; -- SQL Server 2000不支持运行
本查询等价于“查询计算机科学系中年龄不大于19岁的学生。”,为此变通法为:
SELECT * FROM Student WHERE Sdept='CS' AND Sage<=19;
[例24] 查询选修课程1的学生集合与选修课程2的学生集合的差集。
SELECT Sno FROM SC WHERE Cno='1'
EXCEPT(或MINUS)
SELECT Sno FROM SC WHERE Cno='2'; -- SQL Server 2000不支持运行
本例实际上是查询选修了课程1但没有选修课程2的学生。为此变通法为:
SELECT Sno FROM SC
WHERE Cno='1' AND Sno NOT IN
(SELECT Sno FROM SC WHERE Cno='2');
[例25] 查询平均成绩大于85分的学号、姓名、平均成绩。
Select stu_no,sname,avgr
From Student,( Select sno,avg(grade) From SC
Group By sno) as SG(stu_no,avgr)
Where =_no And avgr>85;
SQL-92允许在 From中使用查询表达式,并必须为查询表达式取名。
它等价于如下未使用查询表达式的形式:
Select ,Sname,AVG(Grade)
From Student,SC Where =
Group By ,Sname HAVING AVG(Grade)>85;
[例26] 查出课程成绩在90分以上的女学生的姓名、课程名和成绩。
7 数据库原理与应用实验指导
SELECT SNAME,CNAME,GRADE
FROM (SELECT SNAME,CNAME,GRADE
FROM STUDENT,SC,COURSE
WHERE SSEX='女' AND = AND =)
AS TEMP(SNAME,CNAME,GRADE)
WHERE GRADE>90; -- 特意用查询表达式实现,完全可用其它方式实现
但如下使用查询表达式的查询,则不易改写为其它形式。
[例27] 查询各不同平均成绩所对应的学生人数(给出平均成绩与其对应的人数)。
Select avgr,COUNT(*)
From (Select sno,avg(grade) From SC
Group By sno) as SG(Sno,avgr)
Group By avgr;
[例28] 查出学生、课程及成绩的明细信息及课程门数、总成绩及平均成绩。
SELECT sno,cno,grade -- COMPUTE的其它使用方法,请参阅帮助。
FROM sc
ORDER BY sno
COMPUTE count(cno),SUM(grade),avg(grade) BY sno
[例29] 建立信息系学生的视图(含有学号、姓名、年龄及性别),并要求进行修改和插入操作时仍须保证该视图只有信息系的学生。通过视图查找年龄大于等于18岁的女学生。
CREATE VIEW IS_Student
AS SELECT Sno,Sname,Sage,Ssex
FROM Student
WHERE Sdept='IS' WITH CHECK OPTION;
SELECT * FROM IS_Student WHERE Sage>=18 AND Ssex='女';
[例30] 设有学生-课程关系数据库,其数据库关系模式为:
学生S(学号S#,姓名SN,所在系SD,年龄SA)、课程C(课程号C#,课程名称CN,先修课号PC#)、学生选课SC(学号S#,课程号C#,成绩G)。
试用SQL语言分别写出下列查询(只需写出SQL命令):
(1) 求学生'98001'(为学号)所选的成绩为60以上的课程号。
(2) 求选读了“数据库概论”,并成绩为80或90的学生学号和姓名。
(3) 求选修了全部课程的学生学号、姓名及其所在系名。
(4) 找出没有学生选修的课程号及课程名称。
(5) 列出选课数超过3门的学生学号、其所修课程数及平均成绩。
(6) 删除“数据结构”课程及所有对它的选课情况。
解:
(1) SELECT C# FROM SC WHERE S#='98001' AND G>=60;
(2) SELECT S#,SN FROM S,SC,C
WHERE C.C#= SC.C# AND SC.S#=S.S# AND ='数据库概论'
8 实验4 SQL语言——SELECT查询操作
AND (G=90 OR G=80);
(3) SELECT S#,SN,SD FROM S
WHERE NOT EXISTS(SELECT * FROM C X WHERE NOT EXISTS
(SELECT * FROM SC Y WHERE Y.C#= X.C# AND Y.S#=S.S#));
(4) SELECT C#,CN FROM C WHERE C.C# NOT IN (SELECT SC.C# FROM SC);
(5) SELECT S#,COUNT(C#),AVG(G) FROM SC GROUP BY S# HAVING COUNT(C#)>3;
(6) DELETE FROM SC
WHERE SC.C# IN (SELECT C.C# FROM C WHERE CN='数据结构');
DELETE FROM C WHERE CN='数据结构';
9
2023年6月21日发(作者:)
实验4 SQL语言——SELECT查询操作
实实验验44
SSQQLL语语言言————SSEELLEECCTT查查询询操操作作
实验示例
实验示例中要使用包括如下三个表的“教学管理”数据库JXGL:
(1)学生表Student,由学号(Sno)、姓名(Sname)、性别(Ssex)、年龄(Sage)、所在系(Sdept)五个属性组成,记作:Student(Sno,Sname,Ssex,Sage,Sdept),其中主码为Sno。
(2)课程表Course,由课程号(Cno)、课程名(Cname)、先修课号(Cpno)、学分(Ccredit)四个属性组成,记作:Course(Cno,Cname,Cpno,Ccredit),其中主码为Cno。
(3)学生选课SC,由学号(Sno)、课程号(Cno)、成绩(Grade)三个属性组成,记作:SC(Sno,Cno,Grade),其中主码为(SNO,CNO)。
1、在SQL SERVER查询分析器或企业管理器(以具有相应操作权限的某用户登录)的SQL操作窗口中执行如下命令创建数据库。需要说明的是不同数据库系统其创建数据库的命令或方式有所不同。
CREATE DATABASE JXGL
2、刷新数据库目录后,选择新出现的JXGL数据库,在SQL操作窗口中,创建Student、SC、Course三表及表记录插入命令如下:
Create Table Student
( Sno CHAR(5) NOT NULL PRIMARY KEY(Sno),
Sname VARCHAR(20),
Sage SMALLINT CHECK(Sage>=15 AND Sage<=45),
Ssex CHAR(2) DEFAULT '男' CHECK (Ssex='男' OR Ssex='女'),
Sdept CHAR(2));
Create Table Course
( Cno CHAR(2) NOT NULL PRIMARY KEY(Cno),
Cname VARCHAR(20),
Cpno CHAR(2),
Ccredit SMALLINT);
Create Table SC
( Sno CHAR(5) NOT NULL CONSTRAINT S_F FOREIGN KEY REFERENCES Student(Sno),
Cno CHAR(2) NOT NULL,
Grade SMALLINT CHECK ((Grade IS NULL) OR (Grade BETWEEN 0 AND 100)),
PRIMARY KEY(Sno,Cno),
1 数据库原理与应用实验指导
FOREIGN KEY(Cno) REFERENCES Course(Cno));
INSERT INTO Student VALUES('98001','钱横',18,'男','CS');
INSERT INTO Student VALUES('98002','王林',19,'女','CS');
INSERT INTO Student VALUES('98003','李民',20,'男','IS');
INSERT INTO Student VALUES('98004','赵三',16,'女','MA');
INSERT INTO Course VALUES('1','数据库系统', '5',4);
INSERT INTO Course VALUES('2','数学分析',null ,2);
INSERT INTO Course VALUES('3','信息系统导论','1',3);
INSERT INTO Course VALUES('4','操作系统原理','6',3);
INSERT INTO Course VALUES('5','数据结构','7',4);
INSERT INTO Course VALUES('6','数据处理基础',null,4);
INSERT INTO Course VALUES('7','C语言','6',3);
INSERT INTO SC VALUES('98001','1',87);
INSERT INTO SC VALUES('98001','2',67);
INSERT INTO SC VALUES('98001','3',90);
INSERT INTO SC VALUES('98002','2',95);
INSERT INTO SC VALUES('98002','3',88);
[例1] 查考试成绩大于等于90的学生的学号。
SELECT DISTINCT Sno
FROM SC
WHERE Grade>=90;
这里使用了DISTINCT短语,当一个学生有多门课程成绩大于等于90时,他的学号也只列一次。执行结果如图4-1所示。
图4-1 在查询分析器中的查询执行情况
[例2] 查年龄大于18,并不是信息系(IS)与数学系(MA)的学生的姓名和性别。
SELECT Sname,Ssex
FROM Student
WHERE Sage>18 AND Sdept NOT IN ('IS', 'MA');
在企业管理器中的执行情况如图4-2所示。
图4-2 在企业管理器中的查询执行情况
[说明](1)在企业管理器中打开子窗口的方法:先选中数据库→选中表→在任一表上,按鼠标右键→从快捷菜单中选择“打开表”→点击“返回所有行”子菜单项→在打开返回表内容的子窗口后,按企业管理器工具栏上的“SQL”图标,即能把子窗口分为上下两部分,上面部分能输入不同的SQL命令来执行,执行时按企业管理器工具栏上的“运行”图标
即可;(2)限于篇幅,其它查询命令的执行窗口与运行情况类似于上两图,原则将
2 实验4 SQL语言——SELECT查询操作
不再列出。
[例3] 查以”MIS_”开头,且倒数第二个汉字为“导”字的课程的详细情况。
SELECT * FROM Course
WHERE Cname LIKE ’MIS#_%导_’ ESCAPE ’#’;
[例4] 查询选修了课程的学生人数。
SELECT COUNT(DISTINCT Sno) /* 加DISTINCT 去掉重复值后计数 */
FROM SC;
[例5] 查询计算机系(CS)选修了2门及以上课程的学生的学号。
SELECT
FROM Student,SC
WHERE Sdept='CS' AND =
GROUP BY HAVING COUNT(*)>=2;
[例6] 查询Student表与SC表的广义笛卡尔积。
Select Student.*,SC.*
From Student,SC;
或 Select Student.*,SC.*
From Student Cross Join SC;
[例7] 查询Student表与SC表基于学号SNO的等值连接。
Select *
From Student,SC
WHERE =;
[例8] 查询Student表与SC表基于学号SNO的自然连接。
SELECT , Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student, SC WHERE =;
或 SELECT , Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student INNER JOIN SC ON =;
[例9] 查询课程之先修课的先修课(自身连接例)。
SELECT ,
FROM Course FIRST, Course SECOND
WHERE =;
我们为Course表取两个别名FIRST与SECOND,这样就可以在SELECT子句和WHERE子句中的属性名前分别用这两个别名加以区分。
[例10] 查询学生及其课程、成绩等情况(不管是否选课,均需列出学生信息)。
SELECT , Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student Left Outer JOIN SC ON =;
3 数据库原理与应用实验指导
[例11] 查询学生及其课程成绩与课程及其学生选修成绩的明细情况(要求学生与课程均需全部列出)。
SELECT , Sname, Ssex, Sage, Sdept, , Grade, cname, cpno,
ccredit
FROM Student Left Outer JOIN SC ON = Full Outer join Course
on =;
[例12] 查询性别为男、课程成绩及格的学生信息及课程号、成绩。
SELECT Student.*,Cno,Grade
FROM STUDENT INNER JOIN ON =
WHERE SSEX=’男’ AND GRADE >=60
[例13] 查询与“钱横”在同一个系学习的学生信息。
SELECT * FROM Student
WHERE Sdept IN
(SELECT Sdept
FROM Student
WHERE Sname='钱横');
或 SELECT * FROM Student
WHERE Sdept =
( SELECT Sdept
FROM Student
WHERE Sname='钱横'); -- 当子查询为单列单行值时可以用“=”
或 SELECT S1.*
FROM Student S1,Student S2
WHERE = AND ='钱横';
一般来说,连接查询可以替换大多数的嵌套子查询。
SQL-92支持“多列成员”的属于(IN)条件表达,例:
[例14] 找出同系、同年龄、同性别的学生。
Select * from Student as T
Where (,,) IN
(Select sdept,sage,ssex
From student as S
Where <>); -- SQL Server 2000可能不支持
它等价于逐个成员IN的方式表达,如下(能在SQL Server 2000中执行):
Select * from Student T
Where IN
( Select sdept
From student S
Where <> and
IN
( Select sage
4 实验4 SQL语言——SELECT查询操作
From student X
Where = and <> and
IN
( Select ssex
From student Y
Where = and <>)));
[例15] 查询选修了课程名为“数据库系统”的学生学号、姓名和所在系。
SELECT Sno,Sname,Sdept FROM Student -- IN嵌套查询方法
WHERE Sno IN
( SELECT Sno FROM SC
WHERE Cno IN
( SELECT Cno FROM Course WHERE Cname='数据库系统'));
或 SELECT Sno,Sname,Sdept FROM Student -- IN、= 嵌套查询方法
WHERE Sno IN
( SELECT Sno FROM SC
WHERE Cno=
( SELECT Cno FROM Course WHERE Cname='数据库系统'));
或 SELECT ,Sname,Sdept --连接查询方法
FROM Student,SC,Course
WHERE = AND =
AND ='数据库系统';
或 Select Sno,Sname,Sdept From Student -- Exists嵌套查询方法
Where Exists( Select * From SC
Where = And
Exists( Select * From Course
Where = And Cname='数据库系统'));
或 Select Sno,Sname,Sdept From Student -- Exists嵌套查询方法
Where Exists( Select * From course
Where Cname='数据库系统' and
Exists( Select * From SC
Where = and = ));
[例16] 检索至少不学2和4两门课程的学生学号与姓名。
SELECT Sno,Sname FROM Student
WHERE Sno NOT IN
(SELECT Sno FROM SC WHERE Cno IN ('2','4'));
[例17] 查询其他系中比信息系IS所有学生年龄均大的学生名单,并排序输出。
SELECT Sname FROM Student
WHERE Sage>All(SELECT Sage FROM Student
WHERE Sdept='IS') AND Sdept <> 'IS'
ORDER BY Sname;
本查询实际上也可以用集函数实现:
5 数据库原理与应用实验指导
SELECT Sname FROM Student
WHERE Sage>(SELECT MAX(Sage) FROM Student
WHERE Sdept='IS') AND Sdept<>'IS'
ORDER BY Sname;
[例18] 查询哪些课程只有女生选读。(本题有多于两种表达法)
SELECT DISTINCT CNAME
FROM COURSE C
WHERE '女'=ALL( SELECT SSEX FROM SC,STUDENT
WHERE = AND =);
或 SELECT DISTINCT CNAME FROM COURSE C
WHERE NOT EXISTS
( SELECT * FROM SC,STUDENT
WHERE = AND = AND ='男');
[例19] 查询所有未修1号课程的学生姓名。
SELECT Sname FROM Student
WHERE NOT EXISTS
( SELECT * FROM SC WHERE Sno= AND Cno='1');
或 SELECT Sname FROM Student
WHERE Sno NOT IN (SELECT Sno FROM SC WHERE Cno='1');
但如下是错的:
SELECT Sname FROM Student,SC
WHERE = AND Cno<>'1';
[例20] 查询选修了全部课程的学生姓名(为了有查询结果,自己可调整一些表的)。
SELECT Sname FROM Student
WHERE NOT EXISTS
( SELECT * FROM Course
WHERE NOT EXISTS
(SELECT * FROM SC WHERE Sno= AND Cno=));
由于没有全称量词,我们将题目的意思转换成等价的存在量词的形式:查询这样的学生姓名没有一门课程是他不选的。
本题的另一操作方法是:
SELECT Sname FROM Student,SC WHERE =
Group by ,Sname having count(*)>=(SELECT count(*) FROM Course);
[例21] 查询至少选修了学生98001选修的全部课程的学生号码。
本题的查询要求可以做如下解释,不存在这样的课程y,学生98001选修了y,而要查询的学生x没有选。写成的SELECT语句为:
SELECT Sno
FROM Student SX
WHERE NOT EXISTS
6 实验4 SQL语言——SELECT查询操作
( SELECT * FROM SC SCY
WHERE ='98001' AND
NOT EXISTS
( SELECT * FROM SC SCZ
WHERE = AND =));
[例22] 查询选修了课程1或者选修了课程2的学生学号集。
SELECT Sno FROM SC WHERE Cno='1'
UNION
SELECT Sno FROM SC WHERE Cno='2';
[注意] 扩展的SQL中有集合操作并(UNION)、集合操作交(INTERSECT)和集合操作差(EXCEPT或MINUS)等。SQL的集合操作要求相容即属性个数、类型必须一致,属性名无关,最终结果集采用第一个结果的属性名,缺省为自动去除重复元组,各子查询不带Order By,Order By放在整个语句的最后。
[例23] 查询计算机科学系的学生与年龄不大于19岁的学生的交集。
SELECT * FROM Student WHERE Sdept='CS'
INTERSECT
SELECT * FROM Student WHERE Sage<=19; -- SQL Server 2000不支持运行
本查询等价于“查询计算机科学系中年龄不大于19岁的学生。”,为此变通法为:
SELECT * FROM Student WHERE Sdept='CS' AND Sage<=19;
[例24] 查询选修课程1的学生集合与选修课程2的学生集合的差集。
SELECT Sno FROM SC WHERE Cno='1'
EXCEPT(或MINUS)
SELECT Sno FROM SC WHERE Cno='2'; -- SQL Server 2000不支持运行
本例实际上是查询选修了课程1但没有选修课程2的学生。为此变通法为:
SELECT Sno FROM SC
WHERE Cno='1' AND Sno NOT IN
(SELECT Sno FROM SC WHERE Cno='2');
[例25] 查询平均成绩大于85分的学号、姓名、平均成绩。
Select stu_no,sname,avgr
From Student,( Select sno,avg(grade) From SC
Group By sno) as SG(stu_no,avgr)
Where =_no And avgr>85;
SQL-92允许在 From中使用查询表达式,并必须为查询表达式取名。
它等价于如下未使用查询表达式的形式:
Select ,Sname,AVG(Grade)
From Student,SC Where =
Group By ,Sname HAVING AVG(Grade)>85;
[例26] 查出课程成绩在90分以上的女学生的姓名、课程名和成绩。
7 数据库原理与应用实验指导
SELECT SNAME,CNAME,GRADE
FROM (SELECT SNAME,CNAME,GRADE
FROM STUDENT,SC,COURSE
WHERE SSEX='女' AND = AND =)
AS TEMP(SNAME,CNAME,GRADE)
WHERE GRADE>90; -- 特意用查询表达式实现,完全可用其它方式实现
但如下使用查询表达式的查询,则不易改写为其它形式。
[例27] 查询各不同平均成绩所对应的学生人数(给出平均成绩与其对应的人数)。
Select avgr,COUNT(*)
From (Select sno,avg(grade) From SC
Group By sno) as SG(Sno,avgr)
Group By avgr;
[例28] 查出学生、课程及成绩的明细信息及课程门数、总成绩及平均成绩。
SELECT sno,cno,grade -- COMPUTE的其它使用方法,请参阅帮助。
FROM sc
ORDER BY sno
COMPUTE count(cno),SUM(grade),avg(grade) BY sno
[例29] 建立信息系学生的视图(含有学号、姓名、年龄及性别),并要求进行修改和插入操作时仍须保证该视图只有信息系的学生。通过视图查找年龄大于等于18岁的女学生。
CREATE VIEW IS_Student
AS SELECT Sno,Sname,Sage,Ssex
FROM Student
WHERE Sdept='IS' WITH CHECK OPTION;
SELECT * FROM IS_Student WHERE Sage>=18 AND Ssex='女';
[例30] 设有学生-课程关系数据库,其数据库关系模式为:
学生S(学号S#,姓名SN,所在系SD,年龄SA)、课程C(课程号C#,课程名称CN,先修课号PC#)、学生选课SC(学号S#,课程号C#,成绩G)。
试用SQL语言分别写出下列查询(只需写出SQL命令):
(1) 求学生'98001'(为学号)所选的成绩为60以上的课程号。
(2) 求选读了“数据库概论”,并成绩为80或90的学生学号和姓名。
(3) 求选修了全部课程的学生学号、姓名及其所在系名。
(4) 找出没有学生选修的课程号及课程名称。
(5) 列出选课数超过3门的学生学号、其所修课程数及平均成绩。
(6) 删除“数据结构”课程及所有对它的选课情况。
解:
(1) SELECT C# FROM SC WHERE S#='98001' AND G>=60;
(2) SELECT S#,SN FROM S,SC,C
WHERE C.C#= SC.C# AND SC.S#=S.S# AND ='数据库概论'
8 实验4 SQL语言——SELECT查询操作
AND (G=90 OR G=80);
(3) SELECT S#,SN,SD FROM S
WHERE NOT EXISTS(SELECT * FROM C X WHERE NOT EXISTS
(SELECT * FROM SC Y WHERE Y.C#= X.C# AND Y.S#=S.S#));
(4) SELECT C#,CN FROM C WHERE C.C# NOT IN (SELECT SC.C# FROM SC);
(5) SELECT S#,COUNT(C#),AVG(G) FROM SC GROUP BY S# HAVING COUNT(C#)>3;
(6) DELETE FROM SC
WHERE SC.C# IN (SELECT C.C# FROM C WHERE CN='数据结构');
DELETE FROM C WHERE CN='数据结构';
9
发布评论