!!!文章的编排顺序为:代码+运行结果截图+注释!!!
参考书籍《数据库原理教程(第二版)》范明等编写
以下所有操作都基于参考书籍所给的第四章数据库脚本
如有侵权,请联系我删除该文章
最终解释权归作者本人所有
/*
CREATE DATABASE SchoolDB
GO
USE SchoolDB
GO
创建数据库必须在脚本中首先执行这四行,
其次注意“!执行”该按钮左边的查询目录是否为刚刚创建成功的表,目前我们创建的数据库为“SchoolDB”
现在就可以新建查询开始熟悉各种查询操作了
下边有我给好的课本上所有查询操作语句,选择你不懂的语句执行即可
所有语句都会有“XXX无效”提示,目前不明白为什么,老师上课有提到过但并没有解释。
MySQL中对语句大小写并不敏感,所有语句均不区分大小写
因为MySQL支持选中语句执行,所以操作结束后的“;”本教程部分省略,(没有省略的完全是懒得删了…)
最后祝大家学习愉快
本教程仅供参考!!!
//注释解释:
网上给出了四种注释形式,个人认为可能是版本不同问题,MySQL2014版仅能使用两种注释形式
例如:/**/(可多行注释)
–(仅单行注释)
*/
–不带where的简单查询
select cno,cname,period,credit
from courses;
–查询课程的所有信息,也可把上边的“cno …credit”换成“ * ”
–将上述的select后的列名更改即可查找自己想要的数据
select sname,2017-year(birthday) As age
from students;
–查询“students”中“sname”列和如果现在是2017年,学生的年龄
–select行中的“as”可以省略
select distinct 2017-year(birthday) Age
from students;
–distinct命令可以删除重复的数据
–如果不明白可以把上一条语句中“sname”删除后查询,与该查询操作结果对比理解
–不带where的简单查询到此结束
–带有where的查询
select tname,sex
from teachers
where title='讲师';
–查询所有职称为“讲师”的老师的名字和性别
select distinct sno
from sc
where grade<60
–查询考试成绩不合格的学生的学号
–这里书上把“distinct”命令写成了“distiinct”这应该是印刷错误,无需纠结
select sname,speciality
from students
where year(birthday)between 1997and 1999
–查询出生年月在1997~1999年的学生的姓名和专业
–下边给出相同操作的不同语句
select sname,speciality
from students
where year(birthday)>=1997 and year(birthday)<=1999
select sname,speciality
from students
where year(birthday)not between 1997and 1999
–查询出生年月日不在1997~1999年的学生的姓名和专业
–下边给出相同查询的不同操作语句
select sname,speciality
from students
where year(birthday)<1997 or year(birthday)>1999
–一个小总结:between and语句都可以根据语义改写成and或者or语句
select sno,sname
from students
where speciality in ('计算机科学技术','软件工程')
–查询计算机科学技术和软件工程专业学生的学号和姓名
select sno,sname
from students
where speciality not in('计算机科学技术','软件工程')
–查询既不是计算机科学技术,也不是软件工程专业的学生的学号和姓名
select cname
from courses
where cname like '数据%'
–查询所有以“数据”开头的课程名
select sno,sname
from students
where sname like '李__'
–查询姓李并且名字只有两个汉字的学生的学号和姓名
–书本上有这样一句解释:一个汉字占两个字符位置。
–然而这仅仅是一个书面化的标准说法,在不同的数据库中会有不同的标准。
–有些数据库一个汉字仅占一个字符,很抱歉,我并未找到具体的例子来证明这点。
select *
from courses
where cname like 'C\_%' escape'\'
–查询以“C_”为开头的课程
–这里没有查询结果,并不是因为语句错误,而是我们所用的数据库中并没有相对应的数据
–这里需要注意“_”是通配符,是不可以作为查询条件的符号
–但是现实生活中难免会有例外,所有要用到“escape”命令使通配符成为可查询的符号
–与C++不同,C++只要是“”中的符号默认为不是系统符号(也就是数据库中的通配符)
select sno,cno
from sc
where grade is null
/*查询成绩为空的学生的学号和姓名
这里需要注意,空值是个特殊的值
一个值是空值代表的是没有,并不是0
例如:老师需要确定所有参加考试的学生是否都有成绩,就要用到空值查询
这和一个老师想要查询有没有学生考试成绩是0分,是完全不同的两个概念
注意不要混淆概念
*/
select *
from sc
where cno='cs202'
order by grade desc
–查询选修了“CS202”课程的学生的学号和成绩,并将成绩按降序排序
select *
from sc
order by cno,grade desc
/查询每位学生的每门课程的成绩,并将查询结果按课程号升序,成绩降序排序
order by 语句的形式:order by <排序列>[asc/desc],<排序列>[asc/desc]
其中<排序列>都可以独立按指定升序(asc)或者降序(desc)排序,[]指令缺省时,默认为升序排序/
select count (*) 人数
from sc
where cno='CS302'
–查询选修了CS302课程的学生的人数
–这里与书上程序有出入,结合之前的As使用方法的知识点,这里可以给由新查询产生的新列取名为“人数”
select min(grade)最低分,avg(grade)平均分,max(grade)最高分
from sc
where cno='CS302'
–查询CS302课程的最低分,平均分,最高分
–这里与上条语句一样的修改,使得查询结果更加直观
select sno,AVG(grade)平均成绩
from sc
group by sno
order by AVG(grade) desc
–查询每个学生的平均成绩,输出学生的学号和平均成绩
–书上的查询操作结果会是杂乱无章的顺序,最后一个语句操作实现了倒序排序,使得排序结果直观可视
select sno,avg(grade)平均成绩
from sc
group by sno having avg (grade)>70
order by avg(grade) desc
–查询每个学生的平均成绩,输出平均成绩大于70的学生学号和平均成绩
select cname,grade
from sc,courses
where sc.cno=courses.cno and sno='201705001'
order by grade
–查询学号为201705001的学生的各科成绩,显示每门课程的名字和成绩,并将成绩升序排列
select students.sno,sname,grade
from students,sc
where students.sno=sc.sno and cno='cs202' and grade>50
–查询选修cs202,并且成绩在50分以上的学生的学号,姓名和成绩
select students.sno,sname,cname,grade
from students,sc,courses
where students.sno=sc.sno and sc.cno=courses.cno
order by grade
–查询每个学生选修的每门课程的成绩,要求比较学号、姓名、课程名、和成绩,并将成绩升序排列
select students.sno,sname,avg(grade)平均成绩
from sc,students
where students.sno=sc.sno
group by students.sno,sname
having avg(grade)>70
order by avg(grade)
–查询每个学生的平均成绩,并输入平均成绩大于70分的学生学号、姓名和成绩,并将成绩升序排列
select s2.sname
from students s1,students s2
where s1.birthday=s2.birthday and s1.sname='林艳'and s2.sname<>'林艳'
–查询和林艳出生年份相同的学生的姓名
–下边是嵌套查询的查询操作
select sno,sname
from students
where sex in
(select sex
from students
where sname='林艳')
and speciality in
(select speciality
from students
where sname='林艳')
–查询和林艳相同专业的女同学的学号和姓名
–这里的程序和书上程序大不相同,主要是为了测试是否每个属性后都可以有自己的子查询,测试结果是都可以有自己的子查询
–接下来测试嵌套查询是否可以实现“套娃”操作
select sno,sname
from students
where sex in
(select sex
from students
where sno in
(select sno
from students
where sname='林艳'
))
and speciality in
(select speciality
from students
where sname='林艳')
/*可见嵌套查询是支持“套娃”操作的,这里把套娃操作解释一下:
原理是递归思想,将上边的程序写成伪代码形式如图
查询学号,姓名
从students中查性别,性别是下边子查询的结果
{查询性别
从students中查学号,学号是下边子查询的结果
{查询学号
从students中查姓名,姓名是林艳的学生的学号
}
}
查到了林艳同学的学号,返回学号;
通过返回的学号查到了对应的性别,返回性别;
通过查到的性别和下边查到的专业,最终打印出林艳和林森同学的姓名和学号
*/
–看起来弯弯绕绕很没有意义,完全是在浪费时间,而且不满足程序应有的简洁明了的可读性,但学习研究的乐趣不正在此吗?
–尝试自己感兴趣的方面,并付诸实践,在实践的过程中,你所能积累下来的经验、思考的过程、解决问题的方案,才是最为珍贵的。
select sno,sname,speciality,year(birthday)
from students
where speciality<>'软件工程' and year(birthday)> all (
select year(birthday)
from students
where speciality='软件工程' )
–查询比软件工程所有学生都小的其他专业的学生的学号、姓名、专业和出生日期
–这里需要注意最外层语句中“year(birthday)>all…”这条语句是拿出生日期来做比较,所以越大的值对应的年龄越小
select sno,sname,speciality,year(birthday)出生年份
from students
where speciality<>'软件工程' and year(birthday)>(
select min (year(birthday))
from students
where speciality='软件工程')
order by year(birthday)
–查询比软件工程所有学生都大的其他专业的学生的学号、姓名、专业和出生日期
–由于相同查询的操作并不能更好的看出效果,所以这里选择改动查询目标,使得实际操作时能有更好的理解
select cno,avg(grade)平均成绩
from sc
group by cno
having avg(grade)>= all(
select avg(grade)
from sc
group by cno)
–查询平均成绩最高的课程的课程号和平均成绩
–这里注意,聚集函数是不允许复合的,比如:找平均成绩中的最大值只能像上边一样嵌套查询,而不能通过如下程序解决:
/*select cno,max(avg(grade))
from sc
group by cno*/
select sno,sname
from students s
where exists(
select *
from sc
where sno=s.sno and cno='CS403')
–查询所有选修了课程CS403的学生的学号和姓名
select sno,sname
from students s
where not exists(
select*
from courses c
where not exists(
select *
from sc
where sc.sno=s.sno and sc.cno=c.cno))
–这里用了双重否定的子查询来界定既不也不的查询条件
select sno,sname
from students s
where not exists(
select *
from sc sc1
where sc1.sno='201715122' and not exists(
select *
from sc sc2
where sc2.sno=s.sno and sc1.cno=sc2.cno))
–查询至少选修了学号为201715122的学生选修的全部课程的学生的学号和姓名
–这个操作中“sc2.sno=s.sno”语句的作用是内外表连接条件,辅修专业不需要深入了解
select sno
from sc
where cno='cs301'
union
select sno
from sc
where cno='cs306'
–查询选修了CS031号课程或者CS306号课程的学生的学号
–下边给出等效果的语句
select distinct sno
from sc
where cno='cs301' or cno='cs306'
–并运算比OR语句的优点在于不需要去重的语句
select sno
from sc
where cno='cs301'
intersect
select sno
from sc
where cno='cs306'
–查询选修了CS301号课程,又选修了CS306号课程的学生的学号
–下边给出等效果的语句
select sno
from sc
where cno='CS301' and sno in(
select sno
from sc
where cno='cs306')
–这个程序和书上的程序不同,根据离散数学中的集合运算概念,这里的嵌套查询本身就是交运算的完全等价,不会出现重复的数据,不需要去重
–但是从估计执行计划的查询开销可以看出,无论嵌套查询是否拥有“distinct”语句都不影响查询开销
–考虑书写程序统一性的情况下,顺手加上“distinct”命令是比较好的书写习惯
select sno
from sc
where cno='cs301'
except
select sno
from sc
where cno='cs307'
–查询选修了CS301号课程,但没有选修CS307号课程的学生的学号
–这里与书上程序不同是因为没有选修了CS301号课程,但没有选修CS306号课程的学生,为了使查询有数据可以观察,做了修改
–下边给出等效果的语句
select sno
from sc
where cno='cs301'and
sno not in(
select sno
from sc
where cno='cs307')
–这里的解释与上个程序相同,不再赘述