《数据库系统概论》第三章例题总集

虽然写这个博客主要目的是为了给我自己做一个思路记忆录,但是如果你恰好点了进来,那么先对你说一声欢迎。我并不是什么大触,只是一个菜菜的学生,如果您发现了什么错误或者您对于某些地方有更好的意见,非常欢迎您的斧正!

贯穿这一章的三张表:(真是令人头大!)

Student

学号

Sno

姓名

Sname

性别

Ssex

年龄

Sage

扫描二维码关注公众号,回复: 4233980 查看本文章

所在系

Sdept

201215121

李勇

20

CS

201215122

刘晨

19

CS

201215123

王敏

18

MA

201215125

张立

20

IS

Course

课程号

Cno

课程名

Cname

先行课

Cpno

学分

Ccredit

1

数据库

5

4

2

数学

 

2

3

信息系统

1

4

4

操作系统

6

3

5

数据结构

7

4

6

数据处理

 

2

7

PASCAL语言

6

4

SC

学号

Sno

课程号

Cno

成绩

Grade

201215121

1

92

201215121

2

85

201215121

3

88

201215122

2

90

201215122

3

80

3.4.1表单查询

1.选择表中的若干列

例3.16:查询全体学生的学号和姓名

SELECT Sno,Sname
FROM Student;

例3.17:查询全体学生的姓名、学号、所在系(为了说明各个列的先后顺序可以与表中不一样)

SELECT Sname,Sno,Sdept
FROM Student;

例3.18:查询全体学生的详细记录(为了说明*的用法)

SELECT *
FROM Student;

等价于:

SELECT Sno,Sname,Ssex,Sage,Sdept
FROM Student;

例3.19:查询全体学生的姓名及其出生年份(查询经过计算的值:出生年份要经过计算才能知道)

SELECT Sname,2018-Sage/*出生年份=2018-岁数*/
FROM Student;

结果:

 例3.20:查询全体学生的姓名,出生年份和所在系,要求用小写字母表示系名

SELECT Sname,'Year of Birth:',2018-Sage,LOWER(Sdept)
FROM Student;

输出结果:

用户可以指定别名来改变查询结果的标题:

SELECT Sname,'Year of Birth:' BIRTH,2018-Sage BIRTHDAY,LOWER(Sdept)
FROM Student;

输出结果:

2.选择表中的若干元组

例3.21:查询选修了课程的学生学号(主要讲解DISTINCT,消除相同的行的用法)

没有DISTINCT

SELECT Sno
FROM SC;

输出结果:

有了DISTINCT

SELECT DISTINCT Sno
FROM SC;

输出结果:

例3.23:查询所有年龄在20岁以下的学生姓名及年龄(开始涉及到查询条件

SELECT Sname,Sage
FROM student
WHERE Sage<20;

例3.24:查询考试成绩不及格的学生的学号

SELECT DISTINCT Sno
FROM sc
WHERE Grade<60;

例3.25:查询年龄在20~23岁之间(包括20,23)的学生的姓名、系别和年龄。(注意BETWEEN AND,不在的话就使用NOT BETWEEN AND)

SELECT Sname,Sdept,Sage
FROM student
WHERE Sage BETWEEN 20 AND 23;

例3.27:查询系CS、MA、IS的学生的姓名和性别(谓词IN的使用,不在就用NOT IN

SELECT Sname,Ssex
FROM student
WHERE Sdept IN('CS','MA','IS');/*WHERE Sdept='CS' OR Sdept='MA' OR Sdept='IS';*/

例3.29:查询学号为201215121的学生的详细情况(开始涉及到字符匹配

SELECT *
FROM student
WHERE Sno LIKE '201215121';/*等于WHERE Sno='201215121'*/

例3.30:查询所有性刘的学生的姓名、学号和性别(%的使用)

SELECT Sname,Sno,Ssex
FROM student
WHERE Sname LIKE '刘%';

例3.31:查询姓“欧阳”且全名为3个汉字的学生的姓名_的使用,数据库字符集为ASCII时一个汉字需要两个_,当字符集为GBK时只需要一个)

SELECT Sname
FROM student
WHERE Sname LIKE '欧阳_';

例3.32:查询名字中第二个字为“阳”的学生的姓名和学号

SELECT Sname
FROM student
WHERE Sname LIKE '_阳%';

例3.34:查询DB_Design课程的课程号和学分(ESCAPE'\'表示'\'为换码字符。这样匹配串中紧跟在'\'后面的字符'_'不再具有通配符的定义,转义为普通的“_”字符)

SELECT Cno,Ccredit
FROM course
WHERE Cname LIKE 'DB\_Design' ESCAPE '\';

例3.35:查询以“DB_”开头,倒数第三个字符为i的课程的详细情况。(一句废话:前面的是昨晚弄的,明明保存了草稿,还是差点找不到这个,心态差点崩。嘤嘤嘤)

SELECT *
FROM course
WHERE Cname LIKE 'DB\_%i__' ESCAPE '\';

例3.36:某些学生选修课程后没有参加考试,所以有选课记录,但是没有考试成绩,查询缺少成绩的学生的学号和相应的课程号。(涉及空值的查询)

SELECT Sno,Cno
FROM sc
WHERE Grade is NULL;/*如果是非空就用NOT NULL*/

3.38查询计算机科学系年龄在20岁以下的学生姓名。(多重条件的查询)

SELECT Sname
FROM student
WHERE Sdept='CS' AND Sage<20;

3.39查询选修了3号课程的学生的学号及其成绩,查询结果按分数的降序排列。(这边考察了ORDER BY子句:升序(ASC),降序(DESC))

SELECT Sno,Grade
FROM sc
WHERE Cno='3'
ORDER BY Grade DESC;

3.40查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列。

SELECT *
FROM student
ORDER BY Sdept,Sage DESC;

3.41查询学生总人数(聚集函数COUNT的使用)

SELECT COUNT(*)
FROM student;

3.42:查询选修了课程的学生人数(因为一个学生可能选修多门课,所以要使用DISTINCT

SELECT COUNT(DISTINCT Sno)
FROM student;

3.43:计算选修1号课程的学生平均成绩(聚集函数AVG

SELECT AVG(Grade)
FROM sc
WHERE Cno='1';

3.44:查询1号课程学生的最高分(聚集函数MAX

SELECT MAX(Grade)
FROM sc
WHERE Cno='1';

3.45:查询学生201215012选修课程的总学分数(聚集函数SUM

SELECT SUM(Ccredit)
FROM sc,course
WHERE Sno='201215012' AND sc.Cno=course.Cno;

3.46:求各个课程号及其相应的选课人数(GROUP BY子句:分组后聚集函数将作用于每个组,即每个组有一个函数值)

SELECT Cno,COUNT(Sno)
FROM sc
GROUP BY Cno;/*所有具有相同Cno的人为一组*/

3.47:查询选修了三门以上课程的学生学号

SELECT Sno
FROM sc
GROUP BY Sno/*先用GROUP BY子句按Sno进行分组*/
HAVING COUNT(*)>3;/*再用聚集函数COUNT对每一组进行计数,HAVING短语给出了选择组的条件*/
/*WHERE子句中是不能用聚集函数作为条件表达式的*/

感觉已经忘记的差不多了,因为接下来的题大多涉及的不止一张表,就再放一次。

3.49:查询每个学生及其选修课的情况(连接查询。显然Student与SC表都要涉及,它们的联系是Sno。)

SELECT student.*,sc.*/*注意表名后面的那个. */
FROM student,sc
WHERE student.Sno=sc.Sno;

这是一种等值连接。我们在例3.50中就会看到自然连接。

3.50对例3.49用自然连接完成(也就是Sno只出现一次)

SELECT student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM student,sc
WHERE student.Sno=sc.Sno;

可以看到此时Sno只输出一列

3.51查询选修2号课程(在SC表)成绩在90分以上(在SC表)的所有学生的学号和姓名(在Student表)(WHERE子句是由连接谓词和选择谓词组成的复合条件

SELECT student.Sno,Sname
FROM student,sc
WHERE student.Sno=sc.Sno AND sc.Cno='2' AND sc.Grade>90;

3.52查询一门课的间接选修课(自身连接)(我们看Course表,可以看到比如课程号5的先行课是7,课程号7的先行课又是6,那么课程号5的间接选修课就是6)

SELECT FIRST.Cno,SECOND.Cno
FROM course FIRST,course SECOND
WHERE FIRST.Cpno=SECOND.Cno;

3.53左外连接(想以Student表列出每个学生的基本情况和选课情况,但是某些学生没有选课,仍把Student的悬浮元组保存在结果中)

SELECT student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM student LEFT OUTER JOIN sc ON (student.Sno=sc.Sno);

输出结果:可以看到最后两行虽然没有选课,但是还是放进来了

3.54查询每个学生的学号、姓名(Student 表)、选课的课程名(Course表)成绩(SC表)多表连接

SELECT student.Sno,Sname,Cname,Grade
FROM student,sc,course
WHERE student.Sno=sc.Sno AND sc.Cno=course.Cno;/*连接三个表*/

3.55查询与“刘晨”在同一个系学习的学生(嵌套查询  不相关子查询)

SELECT Sno,Sname,Sdept
FROM student
WHERE
	Sdept IN (
		SELECT Sdept
		FROM student
		WHERE Sname = '刘晨'
	);

解法二:

SELECT S1.Sno,S1.Sname,S1.Sdept
FROM student S1,student S2
WHERE S1.Sdept=S2.Sdept AND S2.Sname='刘晨';

3.56查询选修了课程名为“信息系统”(Course表)的学生学号和姓名(Student表)(这两个表通过SC联系在一起)

SELECT Sno,Sname/*③最后根据学号获取信息*/
FROM student
WHERE Sno IN (/*②然后在SC表找出选修该课程号的学生的学号*/
		SELECT Sno
		FROM sc
		WHERE Cno IN (/*①首先在Course中找出“信息系统”的课程号*/
				SELECT Cno
				FROM course
				WHERE Cname = '刘晨'
			)
	);

3.57找出每个学生超过他自己选修课程平均成绩的课程号(带有比较运算符的子查询)(相关子查询)

SELECT Sno,Cno
FROM sc x/*别名*/
WHERE Grade>=( SELECT AVG(Grade)
		ROM sc y
		WHERE y.Sno=x.Sno);

3.58查询非计算机科学系(CS)中比计算机科学系任意一个学生年龄小的学生姓名和年龄(带有ANY(SOME)或ALL谓词的子查询

SELECT Sname,Sage
FROM student
WHERE Sage<ANY( SELECT Sage
		FROM student
		WHERE Sdept='CS')
AND Sdept<>'CS';

3.60查询所有选修了1号课程(SC表)的学生姓名(Student表)(带有EXISTS谓词的子查询,还有NOT EXISTS

SELECT Sname
FROM student
WHERE EXISTS
    (SELECT*
    FROM sc
    WHERE Sno=student.Sno AND Cno='1');

3.62查询选修了全部课程的学生的姓名(也就说没有一门课程是他不选修的!)

SELECT Sname
FROM student
WHERE NOT EXISTS (
		SELECT *
		FROM course
		WHERE NOT EXISTS (
				SELECT *
				FROM sc
				WHERE Sno = student.Sno
				AND Cno = course.Cno
			)
	);

3.63查询至少选修了学生201215122选修的全部课程的学生号码(也就是说,不存在这样的课程y,学生201215122选修了y,而学生x没有选)

SELECT DISTINCT Sno
FROM sc SCX
WHERE NOT EXISTS
(SELECT *
FROM sc SCY
WHERE SCY.Sno='201215122' AND
NOT EXISTS
(
SELECT *
FROM sc SCZ
WHERE SCZ.Sno=SCX.Sno AND
   SCZ.Cno=SCY.Cno));

3.64查询计算机科学系学生及年龄不大于19岁的学生(并操作UNION

SELECT *
FROM student
WHERE Sdept='CS'
UNION
SELECT *
FROM student
WHERE Sage<=19;

/*或者*/
SELECT *
FROM student
WHERE Sdept='CS' OR Sage<=19;

3.66查询计算机科学系的学生与年龄不大于19岁的学生的交集(交操作INTERSECT

SELECT *
FROM student
WHERE Sdept='CS'
INTERSECT
SELECT *
FROM student
WHERE Sage<=19;

/*或者*/
SELECT *
FROM student
WHERE Sdept='CS' AND Sage<=19;

3.68查询计算机科学系的学生与年龄不大于19岁的学生的差集(差操作EXCEPT

SELECT *
FROM student
WHERE Sdept='CS'
EXCEPT
SELECT *
FROM student
WHERE Sage<=19;

/*或者*/
SELECT *
FROM student
WHERE Sdept='CS' AND Sage>19;

3.60的基于派生表的查询:查询所有选修了1号课程(SC表)的学生姓名(Student表)(使用FROM子句查询

SELECT Sname
FROM student,(SELECT Sno FROM sc WHERE Cno='1')AS SC1/*一定要写别名*/
WHERE student.Sno=SC1.Sno;

再放一次图

3.69将一个新学生元组(学号:201215128,陈冬,男,所在系:IS,18岁)插入到Student中(插入元组

INSERT
INTO student(Sno,Sname,Ssex,Sdept,Sage)
VALUES('201215128','陈冬','男','IS',18);

3.70将学生张成民的信息插入到Student表中(没有认为安排的时候,注意一一对应

INSERT
INTO student
VALUES('201215126','张成民','男',18,'CS');

3.71插入一条选课记录(‘201215128’,‘1’)(自动赋空值

INSERT
INTO sc(Sno,Cno)
VALUES('201215128','1');

/*等同于*/
INSERT
INTO sc
VALUES('201215128','1',NULL);

3.72对于每一个系,求学生的平均年龄,并把结果存入数据库(插入子查询结果

先建立一个新表

CREATE TABLE Dept_age
(Sdept CHAR(15)
Avg_age SMALLINT);
/*再分组*/
INSERT
INTO Dept_age(Sdept,Avg_age)
SELECT Sdept,AVG(age)
GROUP BY Sdept;

3.73将学生201215121的年龄改为22岁(修改某一个元组的值

UPDATE student
SET Sage=22
WHERE Sno='201215121';

3.74将所有学生的年龄增加1岁(修改多个元组的值

UPDATE student
SET Sage=Sage+1;

3.75将计算机科学系全体学生的成绩置零(带子查询的修改语句)

UPDATE sc
SET Grade=0
WHERE Sno IN
(SELECT Sno
FROM student
WHERE Sdept='CS');

3.76删除学号为201215128的学生记录(删除某一个元组的值

DELETE 
FROM student
WHERE Sno='201215128';

3.77删除所有学生的选课记录(删除多个元组的值

DELETE 
FROM sc;

3.78删除计算机科学系所有学生的选课记录(带子查询的删除语句

DELETE 
FROM sc
WHERE Sno IN
(SELECT Sno
FROM student
WHERE Sdept='CS');

3.81从Student表中找出漏填了数据的学生信息(空值的判断:IS NULL,IS NOT NULL

SELECT*
FROM student
WHERE Sname IS NULL OR Ssex IS NULL OR Sage IS NULL OR Sdept IS NULL;

3.83找出选修1号课程的不及格的学生以及缺考的学生(空值的算数运算、比较运算和逻辑运算

SELECT Sno
FROM sc
WHERE Grade<60 AND Cno='1'
UNION
SELECT Sno
FROM sc
WHERE Grade IS NULL AND Cno='1';

/*等于*/
SELECT Sno
FROM sc
WHERE Cno='1' AND (Grade<60 OR Grade IS NULL);

3.85建立信息系学生的视图(建立视图

CREATE VIEW IS_Student
AS
SELECT Sno,Sname,Sage
FROM student
WHERE Sdept='IS'
WITH CHECK OPTION;

3.86建立信息系选修了1号课程的学生的视图(包括学号、姓名、成绩)(行列子集视图

CREATE VIEW IS_S1(Sno,Sname,Grade)
AS
SELECT student.Sno,Sname,Grade
FROM student,sc
WHERE Sdept='IS'AND
	student.Sno=sc.Sno AND
        sc.Cno='1';

3.87建立信息系选修了1号课程且成绩在90分以上的学生的视图(视图可以建立在一个已知视图上

CREATE VIEW IS_S2
AS
SELECT Sno,Sname,Grade
FROM IS_S1/*信息系选修了1号课程的学生*/
WHERE Grade>90;

3.88定义一个反映学生出生年份的视图(带虚拟列的视图

CREATE VIEW BT_S(Sno,Sname,Sbirth)
AS
SELECT Sno,Sname,2014-Sage
FROM Student;

输出结果:

3.89将学生的平均成绩定义为一个视图(分组视图

CREATE VIEW S_G(Sno,Gavg)
AS
SELECT Sno,AVG(Grade)
From SC 
GROUP BY Sno;

输出结果:

3.91删除视图BT_S和视图IS_S1(删除视图

DROP VIEW BT_S;/*成功执行*/
DROP VIEW IS_S1;/*拒绝执行*/
/*由于IS_S1还定义了视图IS_S2,所以要采用级联删除*/
DROP VIEW IS_S1 CASCADE;

3.92在信息系学生的视图中找出年龄小于20岁的学生(视图查询视图消解

SELECT Sno,Sage
FROM is_student
WHERE Sage<20;

视图消解:从数据字典中找到视图的定义,再把定义中的子查询与用户的查询结合起来,转换成等价的对基本表的查询。

本例转换后的查询语句为:

SELECT Sno,Sage
FROM student
WHERE Sdept='IS' AND Sage<20;

3.94在S_G视图(学生的平均成绩视图)中查询平均分在90分以上的学生的学号和平均成绩(WHERE子句不能用聚集函数作为条件表达式

SELECT *
FROM S_G
WHERE Gavg>=90;

本例转换后的查询语句为:(这种写法是错误的!

SELECT Sno,AVG(Grade)
FROM SC
WHERE AVG(Grade>=90)
GROUP BY Sno;

正确的写法为:

SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno
HAVING AVG(Grade>=90);

也可以写为:

SELECT *
FROM (SELECT Sno,AVG(Grade)
      FROM sc
      GROUP BY Sno)AS S_G(Sno,Gavg)
WHERE Gavg>=90;

3.95将信息系学生视图IS_Student中学号为“201215122”的学生姓名改名为“刘辰”。(更新视图:同时会更新基本表

UPDATE IS_Student 
SET Sname='刘辰'
WHERE Sno='201215122';

转换后的语句:

UPDATE Student
SET Sname='刘辰'
WHERE Sno='201215122' AND Sdept='IS';

3.97删除信息系学生视图IS_Student中学号为“201215129”的记录

DELETE 
FROM is_student
WHERE Sno='201215129';
/*转换后*/
DELETE 
FROM Student 
WHERE Sno='201215129' AND Sdept='IS';

到这里,我觉得我以后复习还要看的题目,就全部结束了。感谢您的阅读。爱您!笔芯!❥(^_-)

猜你喜欢

转载自blog.csdn.net/weixin_40851250/article/details/84145975