由于上一篇的篇幅过长,所以实战我直接单独演练吧。
o对了,mysql里面的字符最好都用单引号,否则也许会出错!
课本习题
假设有一个学生选课的数据库,它包含三个关系模式:
student
sno | sname | sex | birth | specialty |
---|---|---|---|---|
20101140101 | 张三 | 男 | 1992-06-01 | CS |
20101140102 | 李四 | 女 | 1991-09-23 | IS |
20101140103 | 王五 | 男 | 1992-05-04 | CS |
20101140104 | 李徜徉 | 男 | 1992-08-09 | MI |
course
cno | cname | credit | category |
---|---|---|---|
001 | C程序设计 | 5 | 必修 |
002 | 数据库系统理论 | 4 | 必修 |
003 | ORACLE基础 | 3 | 选修 |
sc
sno | cno | grade |
---|---|---|
20101140101 | 001 | 85 |
20101140101 | 002 | 78 |
20101140101 | 003 | 90 |
20101140102 | 001 | 87 |
20101140102 | 002 | 89 |
请完成以下练习:
1)用SQL语言完成上述数据库的三张表的定义,包括主码,外码及自定义约束
2)完成每张表的记录录入
3)查询1992年出生的学生的基本信息
4)查询姓“李”的学生
5)查询不是“CS”和“MA”专业的学生的学号和姓名
6)查询“001”号课程的平均成绩
7)查询年龄最大的学生的学号和姓名
8)查询每个学生所选课程的平均成绩
9)查询“CS”专业的男生信息
10)查询与“王五”在用一个专业学习的基本信息(用自然连接查询和嵌套查询两种方式实现)
11)查询每个学生超过他选修课程平均成绩的课程号
12)查询每个学生以及其选修课程情况(要求用左外连接实现)
13)查询至少选修了“001”和“002”号课程的学生的学号
14)将“002”课程的名称改为“数据库系统原理及应用”
15)删除“李四”的选课记录
16)假设“王五”选修了所有的三门课程,将“王五”的学号及其选修的三门课程号(“001”,“002”,“003”)一次插入SC表
17)创建学生选课的视图S_C,包括学号,姓名,课程号,课程名称,成绩
18)在视图S_C基础上,查询学生“张三”的选课情况
1)首先,我们通过例如以下代码将表建好
2)数据录入OK
3)
分析:若要查询一个1992年出生的人员姓名,我们可以从这句话中提取出部分信息:①需要student.birth列作为查询依据②需要整个student表数据。所以我们发现,这两个需要的信息都在同一张表中,那岂不是很好办了么?
select *
from study.student
where student.birth like '1992%';
这样我们就查询正确了!
4)
分析:查询姓“李”的学生,那和上一题有异曲同工之处,只是输出我们可以改成只输出student.sname这一列
select student.sname
from student
where student.sname like '李%';
5)
分析:查询不是“CS”和“MA”专业的学生的学号和姓名,这也好办,直接把where条件改成not like and就ok了
select student.sno,student.sname
from student
where student.specialty not like 'CS' or 'MA';
当然你也可以这么写,因为这是个逻辑问题
select student.sno,student.sname
from student
where (student.specialty not like 'CS') and (student.specialty not like 'MA');
select student.sno,student.sname
from student
where student.specialty not in ('CS','MA');
答案依旧
6)
注意!注意!若使用外键时,主键拥有的数据,外键才能引用,如果外键随便添加主键不存在的数据是无效的!
查询“001”号课程的平均成绩,接下来是有了点难度的了,因为要调用到函数了。首先我们分析一下:要对001课程的选课学生的成绩进行AVG运算,然后看看要选择什么输出什么:①选择sc.cno中值等于’001’的行②对这些行的同表格的sc.grade列的值进行AVG计算,然后输出
select avg(sc.grade)
from sc
where sc.cno='001';
你也可以取个别名好看点
7)
查询年龄最大的学生的学号和姓名,这一看就需要用到聚集函数,思路:①找到student.birth中最小的学生②查询输出出他的学号与姓名
由于聚集函数只能在select和group中书写,而我们又不想输出这个列,所以我们用了嵌套查询来实现
select student.sno, student.sname
from student
where student.birth = (
select min(student.birth)
from student
);
8)
查询每个学生所选课程的平均成绩,说明输出是sc.sno和sc.grade,因此可以①先对sc.sno进行分组,②然后每组的sc.grade进行avg,③最终的结果再和sc.sno拼接
select sc.sno, avg(sc.grade) avg
from sc
group by sc.sno
having avg(sc.grade);
9)
查询“CS”专业的男生信息,那就在student.specialty选中CS的并且student.sex是男的然后输出他们的这表的所有信息
select *
from student
where student.specialty='CS' and student.sex='男';
10)
查询与“王五”在同一个专业学习的基本信息(用自然连接查询和嵌套查询两种方式实现),选出与王五的specialty相等的行,
自然连接
嵌套查询
select distinct *
from student
where student.sname != '王五'
and student.specialty = (
select student.specialty
from student
where student.sname = '王五'
);
11)
查询每个学生超过他选修课程平均成绩的课程号,①输出学号与课程号②sc.grade>avg(sc.grade)③
典型的自身连接+嵌套
select distinct first.sno, first.cno
from sc first
where first.grade >= (
select avg(second.grade)
from sc second
where second.sno = first.sno
)
12)
查询每个学生以及其选修课程情况(要求用左外连接实现),来一个left join,没有where语句的
select distinct student.*,sc.cno
from student left join sc on student.sno = sc.sno;
13)
查询至少选修了“001”和“002”号课程的学生的学号,至少选修001,002,需要输出学生学号,需要用 存在 、联合 函数来设置2个规定条件
select x.sno
from sc x
group by x.sno
having count(x.cno) >= 2
and exists(
select y.sno
from sc y
where y.cno='001'
union
select y.sno
from sc y
where y.cno='002'
)
14)
将“002”课程的名称改为“数据库系统原理及应用”,用update函数
UPDATE study.course t SET t.cname = '数据库系统原理及应用' WHERE t.cno = '002';
15)
删除“李四”的选课记录,诶,我们也可以用删除嵌套查询语句
delete from sc where sc.sno=(
select student.sno
from student
where sname='李四'
);
16)
假设“王五”选修了所有的三门课程,将“王五”的学号及其选修的三门课程号(“001”,“002”,“003”)一次插入SC表,用逗号分割
insert into study.sc
values ('20101140103', '001', null),
('20101140103', '002', null),
('20101140103', '003', null);
17)
创建学生选课的视图S_C,包括学号,姓名,课程号,课程名称,成绩
create view study.S_C as
select student.sno, student.sname, sc.cno, course.cname, sc.grade
from sc,
student,
course
where student.sno=sc.sno and sc.cno=course.cno;
18)
在视图S_C基础上,查询学生“张三”的选课情况
select s_c.sname,s_c.cname
from s_c
where s_c.sname='张三';