实验前准备:JDBC联接数据库
实验内容:
(一)写出教务管理数据库中如下8张表的DDL语句, 要求标识出每张表的主键,包含的外键,明确每个字段的域定义。然后在数据库中创建出这8张表来。
- Course
- Coursetype
- Department
- Enroll
- Speciality
- Student
- Teach
- Teacher
(2)写出DML语句,将上述数据添加到各个表中。
-- 输出信息科学与工程学院(学院编号“24”)2018级学生“李毅”的课程选修成绩单,输出项包括课程名称,学分,成绩三项;
SELECT c.`name`,c.credit,e.score
FROM course c,enroll e
WHERE c.dno = '24' AND c.ctno = (SELECT coursetype.ctno FROM coursetype WHERE coursetype.ctname = '选修课') AND e.sno = (SELECT student.sno FROM student WHERE student.sname = '李毅' AND student.sno LIKE '2018%');
- 对于如下业务需求,写出获取所须数据的SQL语句:
-- 找出学生李毅(学号为 ‘20182401101’)的电话;
SELECT tel
FROM student
WHERE sname = '李毅';
-- 输出信息科学与工程学院(学院编号为’24’)的学生清单,输出项包括姓名,学号,班级三列,按照班级和学号排序;
SELECT sname,sno,classno
FROM student
WHERE dno='24';
-- 输出所有学院的清单,包括学院编号,名称,地址,电话,院长姓名;
SELECT department.dno,department.`name`,department.addr,department.phone,teacher.`name`
FROM department
LEFT JOIN teacher
ON teacher.tno = department.dean;
-- 在2020-1学期选修了周曼玲老师(工号为”2001009”)开设的“数据库系统”课程的学生名单,输出项为五项:教学班,姓名、学号、性别,行政班。要求先按照教学班,再按行政班排序;(注:一个老师在某个学期开的某门课,完全有可能有多个教学班);
SELECT distinct enroll.classno,student.sname,student.sno,student.sex,student.classno
FROM enroll right JOIN student
on enroll.sno=student.sno
WHERE student.sno in (
SELECT enroll.sno
FROM enroll
WHERE year_semeste LIKE '2020-01%'
AND tno = '2001009')
order by enroll.classno,student.classno;
-- 对于在2020-1学期选修了“数据库系统”课程的各行政班,求其平均分,并按照平均分从高到低排序;
SELECT DISTINCT enroll.classno,AVG(score) as AVG_SCORE
FROM enroll
WHERE enroll.cno = ( SELECT course.cno FROM course WHERE course.`name` = '数据库系统' )
group by classno
ORDER BY
AVG_SCORE;
-- 对于信息科学与工程学院(学院编号“24”)在2020-1学期开设的每门课程,输出其选修人数,输出项包括课程名称,选修人数;
SELECT course.`name`,COUNT( DISTINCT enroll.sno ) AS COUNT
FROM course, enroll
WHERE course.dno = '24'
AND course.cno = ANY ( SELECT enroll.cno FROM enroll WHERE enroll.year_semeste LIKE '2020-01%' )
GROUP BY course.`name`;
-- 在2020-1学期,对于开设的“数据库系统”这门课程,在信息科学与工程学院(学院编号“24”)的2018级学生中,有哪些学生没有选修该课程,输出姓名,学号,行政班三项信息;
SELECT sname,sno,classno
FROM student s
WHERE s.dno = '24' AND
NOT EXISTS (
SELECT* FROM enroll e
WHERE e.year_semeste LIKE '2020-01%'
AND s.sno = e.sno
AND e.cno = ( SELECT c.cno FROM course c WHERE c.`name` = '数据库系统' ));
-- 对于在2020-1学期开设的每门课程,输出其最高分、最低分,平均分;
SELECT MAX( score ) AS MAX,MIN( score ) AS MIN,AVG( score ) AS AVG
FROM enroll
WHERE year_semeste LIKE '2020-01%';
-- 对于在2020-1学期开设的“数据库系统”课程,求选修了该课,但是没有及格的学生名单,输出姓名,学号,行政班,课程成绩四项信息;
SELECT sname, sno,classno
FROM student s
WHERE EXISTS (
SELECT * FROM enroll e
WHERE e.year_semeste LIKE '2020-01%'
AND e.score < '60'
AND s.sno = e.sno
AND e.cno = ( SELECT c.cno FROM course c WHERE c.`name` = '数据库系统' ));
-- 对于信息科学与工程学院(学院编号“24”)的每个教师,统计出其在2019年度的教学工作量;(提示:课程表中,每门课有课时量hours字段)
SELECT teacher.`name`, SUM( course.hours ) AS SUM
FROM teacher, course
WHERE course.cno = ANY (
SELECT enroll.cno
FROM enroll
WHERE enroll.year_semeste LIKE '2019%'
AND enroll.tno = ANY ( SELECT teacher.tno FROM teacher WHERE teacher.dno = '24' ))
GROUP BY teacher.`name`;
-- 统计各个学院在2019年度的教学工作量;
SELECT department.`name`, SUM( course.hours )
FROM department, course
WHERE department.dno = ALL (
SELECT course.dno
FROM course
WHERE course.cno = ALL ( SELECT enroll.cno FROM enroll WHERE enroll.year_semeste LIKE '2019%' ))
GROUP BY department.`name`;
-- 对于2016级学生,即将毕业,求出输出所得总学分不足172的学生,输出项为所属学院名称,学号,姓名,已得学分数这四项;
SELECT department.`name`,student.sno,student.sname,SUM( course.credit ) AS SUM
FROM department, student,course
WHERE department.dno = student.dno
AND course.cno = ALL (
SELECT enroll.cno
FROM enroll
WHERE enroll.sno = ALL ( SELECT student.sno FROM student WHERE student.sno LIKE '2016%' ))
GROUP BY student.sno
HAVING SUM( course.credit ) < '172';
附加部分:
分析所给出的SQL语句的含义,理解和注释出每个语句的目的。然后上机执行数据操作SQL语句,得出正确结果。
查询迪斯尼1999年发行的电影的名字与片长,名字字段命名为“name”,片长字段命名为“lengthInHours”,以小时为单位:
select title as name , length*0.016667 as lengthInHours from movies
where studioName='Disney' and year=1999;
查询迪斯尼1999年发行的电影的名字与片长,名字字段命名为“name”,片长字段命名为“length”,以小时为单位,并用名为“InHours”的一列记录电影片长的单位(hrs.):
select title as name , length*0.016667 as length, 'hrs.' as InHours from movies
where studioName='Disney' and year=1999;
-- 查询Fox在1970年之后发行的片长在90分钟以内的电影的名字:
select title from movies where (year>1970 or length<90) and studioName='Fox';
-- 在电影表中查询以“Star”开头的电影的名字:
select title from movies where title like 'Star %';
-- 在不存在的“dual”表格中查询常量date:
select date '1948-05-14', time '12:08:08.08' from dual;
select date '1948-05-14', time '12:08:08.08' from dual;
select date '1948-05-14', timestamp '1948-05-14 12:08:08.08' from dual;
-- 在不存在的“dual”表格中查询1+2、1+null、null+1的结果:
select 1+2 , 1+null,null+1 from dual;
-- 查询电影表中满足1=1的电影的详细信息:
select * from movies where 1=1;
-- 查询电影表中满足null=null的电影的详细信息:
select * from movies where null=null;
-- 查询电影表中title字段非空的电影的详细信息:
select * from movies where title is not null;
-- 查询电影表中的全部记录,并使用排他锁:
select * from movies for update;
-- 查询电影表中的片长不超过120分钟或超过120分钟的电影:
select * from movies where length<=120 or length>120;
-- 查询电影表中title字段为空的电影的详细信息:
select * from movies where title is null;
-- 查询电影表中Fox发行的全部电影的详细信息,按片长与片名升序排序:
select * from movies where Studioname = 'Fox' order by length, title;
-- 查询片名为“Star Wars”,movieexec表中cert字段等于movie表中producerc字段的电影在movieexec表中的名字:
select name from movies, movieexec where title='Star Wars' and producerc= cert;
-- 查询moviestar表中的住址与movieexec表中的住址相同的记录,
-- 在两个表格中的名字:
select moviestar.name, movieexec.name from moviestar , movieexec where moviestar.address =
movieexec.address;
-- 查询住址相同的不同电影明星的名字,结果成对出现:
select star1.name, star2.name from moviestar star1, moviestar star2 where star1.address = star2.address
and star1.name<star2.name;
-- 查询电影明星表中可能出现关联的两人名字,结果成对出现:
select star1.name, star2.name from moviestar star1, moviestar star2;
-- 查询电影“Star Wars”的出品方的名字:
select name from movieexec where cert =( select producerc from movies where title='Star Wars' );
-- 查询姓名为“Harrison Ford”的明星参演的电影的出品方的名字:
select name from movieexec where cert in ( select producerc from movies where (title, year) in (select
movietitle, movieyear from starsin where starname='Harrison Ford' ));
-- 通过联接查询姓名为“Harrison Ford”的明星参演的电影的出品方的名字:
select name from movieExec, movies, starsin where cert = producerC and title = movietitle and year=
movieyear and starname='Harrison Ford';
-- 查找有多个版本的电影中的老版本的名字与年代。
select title, year from movies old where year <any (select year from movies where title = old.title) ;
select name from movieexec, (select producerc from movies, starsin where title = movietitle and year =
movieyear and starname = 'Harrison Ford') prod where cert = prod.producerc;
-- 查询movies表与starsin表的笛卡尔积:
select * from movies cross join starsin ;
-- 查询姓名为“Harrison Ford”的明星出演的所有电影的出品方,如果有重复便输出多次:
select * from movies join starsin on title=movietitle and year = movieyear;
select title, year, length, genre, studioName, producerc, starname from movies join starsin on
title=movietitle and year = movieyear;
-- 将movies表与starsin表自然联结:
select * from movies natural join starsin ;
-- 将moviestar表与movieexec表自然联结:
select * from moviestar natural join movieexec ;
-- 将movieexec表与moviestar表左联接的结果与右联接的结果合在一起输出,联接字段为name:
select * from moviestar left outer join movieexec on moviestar.name= movieexec.name
union select * from moviestar right outer join movieexec on moviestar.name= movieexec.name;
-- 不指定联接字段,将movieexec表与moviestar表左联接,观察能否输出结果:
select * from moviestar left outer join movieexec ;
select * from moviestar right outer join movieexec ;
-- 将movies表与starin表左联接的结果与右联接的结果合在一起输出,联接字段为左表的title、year分别对应右表的movietitle、movieyear:
select * from movies left outer join starsin on title = movietitle and year=movieyear
union
select *from movies right outer join starsin on title = movietitle and year=movieyear;
-- 将movies表与starin表左联接,联接字段为左表的titile、movietitle分别对应右表的year、movieyear:
select * from movies left outer join starsin on title = movietitle and year=movieyear;
-- 将movies表与starin表右联接,联接字段为左表的titile、movietitle分别对应右表的year、movieyear:
select * from movies right outer join starsin on title = movietitle and year=movieyear;
-- 查询不重复的所有电影名
select distinct title from movies;
-- 查询movie表中全部记录的title、year,查询starin表中所有记录的movietitle、movieyear,对两个结果集进行不去重的并集操作:
select title, year from movies
union all select movietitle as title , movieyear as year from starsin;
-- 查询movieexec表中所有记录networth的平均值:
select avg(networth) from movieexec;
-- 查询starin表中的记录数目:
select count(*) from starsin;
-- 查询starin表中starname的数目:
select count(starname) from starsin;
-- 查询starin表中不同的starname的数目:
select count(distinct starname) from starsin;
-- 查询所有制片厂的制片总长度:
select studioname,sum(length) from movies group by studioname;
-- 在movies表中查询不同的制片厂的名字:
select studioname from movies group by studioname;
-- 在movies表中查询不同的制片厂的名字:
select distinct studioname from movies group by studioname;
drop table tmp_a;
-- 创建一个名为temp_a的表,有两个字段:a和b,数据类型都是varchar(8):
CREATE TABLE TMP_A ( A varchar(8), b varchar(8));
-- 向该表中插入一行记录,该记录全部字段为NULL。
insert into tmp_a values(null,null);
-- 查询tmp_a表中的全部记录:
select * from tmp_a;
-- 查询tmp_a表中b字段的记录数量:
select a, count(b) from tmp_a group by a;
-- 查询在1985年之前发行过电影的制片厂的电影总时长:
select name, sum(length) from movieExec , movies where producerc = cert group by name having
min(year)<1985;
-- 查询制片厂1985年之前发行的所有电影的总时长:
select name, sum(length) from movieExec , movies where producerc= cert and year<1985 group by name
having min(year)<1985;
-- 向starsin表中插入一条记录,movietitle为The maltese falcon,movieyear为1942,starname为Sydney Greenstreet:
insert into starsin(movietitle, movieyear, starname) values('The maltese falcon',1942,'Sydney Greenstreet');
-- 向studio表中插入movies表中存在但studio表中不存在的记录
insert into studio(name) select distinct studioname from movies where studioname not in (
select name from studio);
-- 删除starsin表中指定的记录:指定要删除的记录的movietitle、movieyear、starname:
delete from starsin where movietitle='The maltese falcon' and movieyear=1942 and starname='Sydney
Greenstreet';
-- 更新movieexec中的cert字段值存在于studio表中的记录,将对应记录的name修改为“Pres.”。
update movieexec set name = 'Pres.' where cert in (select presc from studio);