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

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

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

Student

学号

Sno

姓名

Sname

性别

Ssex

年龄

Sage

所在系

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