《数据库原理MySQL》第四次上机实验

一、连接查询

1.查询女学生的学生学号及总成绩

SELECT s.sno,SUM(degree)
FROM student s
RIGHT JOIN sc r
ON s.sno=r.sno
WHERE ssex='女'
GROUP BY s.sno

2.查询李勇同学所选的课程号及成绩

SELECT r.cno,degree
FROM sc r
LEFT JOIN student s
ON r.sno=s.sno
WHERE sname='李勇'

3.查询李新老师所授课程的课程名称

SELECT c.cname
FROM course c
RIGHT JOIN teaching g
ON c.cno=g.cno
INNER JOIN teacher t
ON g.tno=t.tno
WHERE tname='李新'

4.查询女教师所授课程的课程号及课程名称

SELECT c.cno,c.cname
FROM course c
RIGHT JOIN teaching g
ON c.cno=g.cno
INNER JOIN teacher t
ON g.tno=t.tno
WHERE tsex='女'

5.查询姓“王”的学生所学的课程名称

SELECT c.cname
FROM course c
RIGHT JOIN sc r
ON c.cno=r.cno
INNER JOIN student s
ON r.sno=s.sno
WHERE sname LIKE '王%'

6.查询选修“数据库”课程且成绩在 80 到 90 之间的学生学号及成绩

SELECT r.cno,degree
FROM sc r
INNER JOIN course c
ON r.cno=c.cno
WHERE cname='数据库'
AND degree BETWEEN 80 AND 90

7.查询选修“C03”课程的学生的平均年龄

SELECT AVG(YEAR(CURDATE())-YEAR((Sbirthday))) 平均年龄
FROM student s
RIGHT JOIN sc
ON s.sno=sc.sno
WHERE cno='C03'

8.查询学习课程名为“数据库”的学生学号和姓名

SELECT s.sno,sname
FROM student s
RIGHT JOIN sc
ON s.sno=sc.sno
INNER JOIN course c
ON sc.cno=c.cno
WHERE c.cname='数据库'

9.查询”李新”教师任课的课程号,选修其课程的学生的学号和成绩

SELECT g.cno,sno,degree
FROM teaching g
RIGHT JOIN sc
ON sc.cno=g.cno
LEFT JOIN teacher t
ON g.tno=t.tno
WHERE tname='李新'

10.查询在第 3 学期所开课程的课程名称,选修其课程的学生学号和成绩

SELECT c.cname,sno,degree
FROM course c
RIGHT JOIN sc
ON c.cno=sc.cno
LEFT JOIN teaching g
ON sc.cno=g.cno
WHERE cterm=3

二、嵌套查询
1.查询至少选修两门课程的男学生姓名

SELECT s.sname
FROM student s
WHERE ssex='男'
AND sno=(
	SELECT sno
	FROM sc
	GROUP BY sno
	HAVING COUNT(sno)>=2
)

2.查询与刘晨同一个系的同学姓名;

SELECT s.sname
FROM student s
WHERE sname!='刘晨' 
AND sdept=(
	SELECT sdept
	FROM student
	WHERE sname='刘晨'
)

3.查询学号比刘晨同学小,而年龄比他小的学生姓名,并写出 MySQL 中 sysdate()和 now()函数的功能差别。

SELECT s.sname	
FROM student s
WHERE sno<(SELECT sno FROM student WHERE sname='刘晨')
AND (YEAR(CURDATE())-YEAR(Sbirthday))<(
	SELECT (YEAR(CURDATE())-YEAR(Sbirthday))
	FROM student
	WHERE sname='刘晨'
)

NOW():基于语句开始执行的时间
SYSDATE():系统实时时间,有延迟导致时间不一致,主库和从库执行时返回值不一样

4.查询出生日期大于所有男同学出生日期的女同学的姓名及系别

SELECT s.sname,sdept
FROM student s
WHERE ssex='女'
AND YEAR(Sbirthday)>ALL(
	SELECT YEAR(sbirthday)
	FROM student 
	WHERE ssex='男'
)

5.查询成绩比该课程平均成绩高的学生的学号、课程号及成绩

SELECT cno,degree
FROM sc r
WHERE r.degree>(
	SELECT AVG(degree)
	FROM sc
	WHERE sc.cno=r.cno
)

6.查询不讲授“C01”课的教师姓名

SELECT t.tname
FROM teacher t
WHERE tno NOT IN(
	SELECT tno
	FROM teaching g
	WHERE cno='C01'
)

7.查询没有选修“C02”课程的学生学号及姓名

SELECT s.sno,sname
FROM student s
WHERE sno NOT IN(
	SELECT sno
	FROM sc
	WHERE cno='C02'
)

8.查询选修了“数据库”课程的学生学号、姓名及系别

SELECT s.sno,sname,sdept
FROM student s
WHERE sno IN(
	SELECT sno
	FROM sc
	INNER JOIN course c
	ON sc.cno=c.cno
	WHERE cname='数据库'
)

9.查询选修了全部课程的学生姓名

SELECT s.sname
FROM student s
WHERE sno IN(
	SELECT sno
	FROM sc
	GROUP BY sno
	HAVING COUNT(sno)=(
		SELECT COUNT(cno)
		FROM course
	)
)

10.分别用子查询和连接查询,求“C01”号课程在 80 分以上的学生信息
子查询:

SELECT *
FROM student s
WHERE sno IN(
	SELECT sno
	FROM sc
	WHERE cno='C01'
	AND degree>80
)

连接查询:

SELECT s.*
FROM student s
LEFT JOIN sc r
ON s.sno=r.sno
WHERE cno='C01'
AND degree>80

三、数据更新
1.向 Student 表中插入记录(‘20050203’,‘张静’,‘女’,‘1981-3-21’,‘CS’ ,‘电子商务’)

INSERT INTO `student`(`sno`,`sname`,`ssex`,`sbirthday`,`sdept`,`speciality`)
VALUES('20050203','张静','女','1981-3-21','CS' ,'电子商务')

2.插入学号为 ‘20050302’,姓名为’李四’学生信息

INSERT INTO `student`(`sno`,`sname`)
VALUES('20050302','李四')

3.把男学生记录保存到表 TS 中

CREATE TABLE ts(
	SELECT * 
	FROM student 
	WHERE ssex='男'
)

4.将学号为’ 20150202’ 的学生姓名改为’张华’,系别改为“CS”,专业改为“多媒体技术”

UPDATE `student` 
SET `sname`='张华',`sdept`='CS',`Speciality`='多媒体技术'
WHERE sno=20050202

5.将 ‘20150201’ 学生选修“C03”号课程的成绩改为该课的平均成绩

UPDATE `sc`
SET degree=(
	SELECT * FROM(
		SELECT AVG(degree)
		FROM sc
		WHERE cno='C03'
	) a
)
WHERE sno='20050201'
AND cno='C03'

6.把女同学的成绩提高 5%

UPDATE `sc`
SET degree=(1+0.05)*degree 
WHERE sno IN(
	SELECT sno
	FROM student
	WHERE ssex='女'
)

7.(1) 把选修了“数据库”课程学生的成绩全改为空值(NULL)

UPDATE `sc`
SET degree=NULL
WHERE cno IN(
	SELECT cno
	FROM course
	WHERE cname='数据库'
)

(2) 将’01’课程的成绩更新为随机成绩数据,成绩取值范围为 0 到 100 之间。

UPDATE `sc`
SET degree=FLOOR(RAND()*100)
WHERE cno='C01'

8.删除学号为 20150302 的学生记录

DELETE FROM student
WHERE sno=20050302

9.把“刘晨”同学的选课记录全部删除

DELETE FROM sc
WHERE sno IN(
	SELECT sno
	FROM student
	WHERE sname='刘晨'
)

10.删除电子商务专业所有学生的选课记录

DELETE FROM sc
WHERE sno IN(
	SELECT sno
	FROM student
	WHERE speciality='电子商务'
)

思考题
1.使用存在量词[NOT]EXISTS 的嵌套查询时,何时外层查询的 WHERE 条件为真,何时为假?

exists对外表用loop逐条查询,每次查询都会查看exists的条件语句,当exists里的条件语句能够返回记录行时(无论记录行是的多少,只要能返回),条件就为真,返回当前loop到的这条记录,反之如果exists里的条件语句不能返回记录行,则当前loop到的这条记录被丢弃,exists的条件就像一个bool条件,当能返回结果集则为true,不能返回结果集则为false

2.DROP 命令和 DELETE 命令的本质区别是什么?如何恢复通过 DELETE FROM 命令删除的数据。

  1. 触发条件不同
    delete语句是数据库操作语言(dml),这个操作会放到rollbacksegement中,在事务提交后生效,执行时触发相应的trigger。
    drop是数据库定义语言(ddl),操作立即生效,原数据不放到rollbacksegment中,不能回滚,操作不触发trigger。
  2. 用法不同
    delete只删除内容、释放空间但不删除定义,而delete即可以对行数据进行删除,也可以对整表数据进行删除。
    drop是删除内容和定义,并释放空间。执行drop语句,将使此表的结构一起删除。
  3. 执行速度不同
    drop的执行速度大于delete。
    delete的执行速度小于drop

如何恢复:Delete语句误操作只会删除表数据,而表结构还在。找到数据库的binlog存放位置,利用mysqlbinlog命令的–start-datetime参数快速定位数据位置.

确定起始位置点:

mysqlbinlog -vv --start-datetime='2022-05-19 17:20:00' on.000004| head -1000 |more

确定终止位置点:

mysqlbinlog -vv --start-datetime='2022-05-19 17:20:00' --stop-datetime='2022-05-19 17:23:00' on.000004| tail -1000 |more

将待恢复数据导出

mysqlbinlog -vv --start-position=192 --stop-position=435 on.000004 |grep ^"###" >/tmp/bin_data

将DELETE语句转换为INSERT语句

cat /tmp/bin_data | sed -n '/###/p' | sed 's/### //g;s/\/\*.*/,/g;s/DELETE FROM/INSERT INTO/g;s/WHERE/SELECT/g;' |sed -r 's/(@6.*),/\1;/g' | sed 's/@[1-9]=//g' | sed 's/@[1-9][0-9]=//g' >/tmp/student.sql

将INSERT语句导入数据库中

mysql -hlocalhost -P3306 -uroot -pyL@98 > /tmp/student.sql

即可完成数据恢复

3.利用 INSERT、UPDATE 和 DELETE 命令可以同时对多个表操作吗,如果需要同时操作多个表,如何实现?

INSERT、UPDATE和DELETE 只能对单表操作
要操作多表,可以用触发器

猜你喜欢

转载自blog.csdn.net/Aurinko324/article/details/124867865