第三章 关系数据库SQL
三、SQL查询
select [distinct] (去重)所查内容 from 所查询的表(可多个)where 要求条件
例:查计算机科学系全体学生
select Sname from Student where Sdept=‘CS’;
查询所有年龄在20岁以下的学生的学号和年龄
select Sno,Sage from Student where Sage<20;
(1)范围
①between … and … 在…之间
例:查询年龄在20岁~23岁之间的学生姓名、系别和年龄
select Sname,Sdept,Sage from Student where Sage between 20 and 30;
②not between…and… 不在…之间
例:查询年龄不在20岁~23岁之间的学生姓名、系别和年龄
select Sname,Sdept,Sage from Student where Sage not between 20 and 30;
(2) 确定集合
①in:查找属性值属于指定集合的元组(相当于数学中的属于€)
例:查询计算机科学系(CS)、数学系(MA)、信息系(IS)学生的姓名和性别
select Sname,Ssex from Student where Sdept in(‘CS’,‘MA’,‘IS’);
②not in:查找属性值不属于指定集合的元组
查询不是计算机科学系(CS)、数学系(MA)、信息系(IS)学生的姓名和性别
select Sname,Ssex from Student where Sdept not in(‘CS’,‘MA’,‘IS’);
(3)like 模糊查询
①%:表示任意长度
例:查询所有姓刘的学生的姓名、学号和性别
select Sname,Sno,Ssex from Student where Sname like ‘刘%’;
②_:表示任意单个字符
例:查询姓’欧阳’且全名为三个汉字的姓名和学号
select Sname,Sno from Student where Sname like ‘欧阳_’;
③若想查的字符本身含有_或%,则在_前加入\(空格) ‘ESCAPE’ \ '(换码字符):作用是将\后面的_ 转为普通字符,不表示通配符含义
例:查询以“DB_”开头,且倒数第三个字符为i的课程的详细情况
select * from Course where Cname like ‘DB_%i_ _’ ESCAPE ’ \ ';
①and :查询满足and两边的条件
例:查询计算机科学系年龄在20岁以下的学生姓名
select Sname from Student where sdept=‘CS’ and Sage<20;
②or:查询结果满足两边一个条件就可以
例:查询计算机科学系(CS)、数学系(MA)、信息系(IS)学生的姓名和性别
select Sname,Ssex from Student where Sdept=‘CS’ or Sdept=‘MA’ or Sdept=‘IS’;
③not:否定
(5)
①is null(null:表示不确定)
例:某些学生选修课程后没有参加考试,所以有选修记录,但没有考试成绩。查询缺少成绩的学生的学号和相应的课程号。
select Sno,Cno from SC where Grade is null;
②is not null
查询所有有成绩的学生的学号和相应的课程号。
select Sno,Cno from SC where Grade is not null;
例:查询学生总人数
select count * from Student
(2)count([distinct] A):计算属性A有多少个值(加[distinct]表示有多少个不同的值)
例:查询选修了课程的学生数
select count(distinct Sno) from Sc;这里的distinct表示一个人选多门课程,但是只记录1次
(3)sum([distinct] A):A的属性上所有元组加一起求和(必须为数值型)
例:查询学生201215012选修课程的总学分数
select sum(Credit) from Sc,Course where Sno=‘201215012’ and Sc.Cno=Couse.Cno;
(4)avg([distinct] A):对A的属性上所有元组求平均值(必须为数值型)
例:计算选修1号课程的学生平均成绩
select avg(grade) from Sc where Cno=‘1’;
(5)max([distinct] A):求属性A的最大值
例:查询选修1号课程的学生最高分数
select max(grade) from Sc where Cno=‘1’;
(6)min([distinct] A):求属性A的最小值
select [distinct] 所查内容
from 所查询的表(可多个)
where 条件或链接或嵌套
group by 属性 对属性相同的值进行1列或多列分组
having 条件 对group by得到的组进行筛选
order by_(desc:对查询结果的一个或多个属性升序(降序排列))
例:求各个课程号及相应选课人数
select Cno,count(Sno) from Sc group by Cno;
这里的Sno用于识别是哪一门课程;group by ;分组Cno;cno组标签
例:查询平均成绩大于等于90分的学生学号和平均成绩
select sno,avg(grade) from Sc group by sno having avg(grade>=90);
错误语句:
select sno,avg(grade) from Sc where avg(grade>=90 group by sno;
注:where不能用聚集函数作为条件表达式的
(1)用法:所查询信息不能在一个表中查出来,将多个表连接
(2)等值连接:运算符= ;非等值连接:其他运算符>、<…
例:查询每个学生及其选修课程的情况
select student.* ,sc.* from student,sc where student.sno=sc.cno;
(3)自然连接:在等值连接的基础上把重复属性列去掉
例:查询每个学生及其选修课程的情况
select student.sno,sname,ssex,sage,sdept,cno,grade from student,sc where studen,sno=sc.sno;
这里的Sno两个表中都有,注意区分
(4)自身连接:自己与自己做笛卡尔积,再按连接条件做选择操作
第一个表的每一行元组与第二个表的所有行元组拼接
例:查询每一门课程的间接先行课(先行课的先行课)
select first.cno,second.cpno from course first,course second where first.cpno=second.cno;
(5)外连接:悬浮元组保存在结果关系中
(6)多表连接:涉及到查询的结果在多个表中,需要将多表连接在一起
例:查询每个学生的学号、姓名、选修课程名及成绩
select Student,Sname,Cname,grade from Student,Sc,Course where Student.Sno and Sc.cno=Course.cno;找公共属性,snocno将Sc表和Course表和student拼接在一起
(1)分类
⑴不相关子查询:子查询的查询条件不依赖于父查询
例①:查询选修了2号课程的学生姓名
第一步找课程号为2的学生的学号,假设这里理解为一个集合它是包含课程号为2的所有学生的学号; select sno from student where cno=‘2’;然后再在这个集合里面找对应学号的学生姓名 select sname from student where sno;
这两个用IN连接,表示嵌套
select sname from student where sno IN (select sno from student where cno=‘2’);
例:②查询选修了课程名为“信息系统”的学生学号和姓名
解法1:因为信息系统课在Course表里面,而学生姓名和学号在Student表中,两者没有公共属性无法用连接查询,所以要借助SC表作为中间关系找到公共属性将两个表连接起来,这样就变为3表连接
select student.sno,sname from student,sc,course where student.sno=sc.sno and sc.cno=course.cno and course.cname=‘信息系统’;
解法2:第一步先找课程名为信息系统的课程号select cno from course where cname=‘信息系统’;其次在SC表中找选修了信息系统的学号select sno from sc where cno;这样就可以知道那各学号选修了信息系统这门课最后找学号所对应的学生姓名select sno,student from student where sno,将这3个用IN做嵌套
select sno,student from student where sno IN (select sno from sc where cno IN (select cno from course where cname=‘信息系统’));
⑵相关子查询:子查询的查询条件依赖于父查询
例:找出每个学生超过他自己选修课程平均成绩的课程号
第一步先找课程号select cno from sc x(x别名);第二步在表中查平均成绩select avg(grade) from sc y(别名)
sno:作用标注哪个学生超过他平均成绩
y.sno=x.sno相关子查询,查询的y的学号依赖于父查询x
每个学生都有自己的平均成绩,子查询要查询的平均成绩要依赖于父查询对应的哪个学生查
select sno,cno from sc x where grade>=(select avg(grade) from sc y) where y.sno=x.sno);
(2)in
(3)比较运算符
(4)any,all谓词子查询
>any 大于子查询结果中某个值
>all 大于子查询结果中所有值
<>any不等于子查询结果中某个值
<>all不等于子查询结果中任何一个值
例:查询非计算机科学系中比计算机科学系有学生年龄都小的学生姓名及年龄
这里的计算机科学系是一个参照体
select sname,sage from student where sage<All (select sage from student where sdept=‘CS’) and sdept <> ‘CS’;
(5)谓词子查询
⑴exists(存在)
⑵not exists(不存在)
例:查询没有选修1号课程的学生姓名
select sname from student where not exists(select * from sc where sno=student.sno and cno=‘1’);
select * from sc where sno=student.sno and cno=‘1’;是指查询选修了1号课程的信息,而题目要求查询不是选修1号课程的信息,所以取它的补集就是没有选修1号课程的信息
*:表示查询一个表中的所有信息
例:查询既选修了1号课程又选修了2号课程的学生。
既选1号课程又选2号课程select sno from sc where cno=‘1’; and cno=2;这是错误的,不能保证所查的属性既是1号课程又是2号课程,采用集合交,第1步找选修了1号课程select sno from sc where cno=‘1’;第2步找选修了2号课程select sno from sc where cno=‘2’;将两个条件交,度保证能够满足。
select sno from sc where cno=‘1’ INTERSECT select sno from sc where cno=‘2’;
(2)union(并):满足一个条件
例:查询选修了1号课程或者选修了2号课程的学生。
或者;采用集合并,第1步找选修了1号课程select sno from sc where cno=‘1’;第2步找选修了2号课程select sno from sc where cno=‘2’;将两个条件并,满足其中1个即可。
select sno from sc where cno=‘1’ UNION select sno from sc where cno=‘2’;
(3)except(差):
例:查询计算机科学系的学生与年龄不大于19岁的学生的差集。
直接将两个语句用EXCEPT连接
select * from student where sdept=‘CS’ EXCEPT select * from student where sage<=19;
子查询不仅可以出现在where子句中,还可以出现在from子句中,这时子查询生成临时派生表成为主查询的查询对象。
(1)插入元组
insert into 表名(属性1,属性2…)values (‘值1’,‘值2’…)
值和属性要一 一对应
例:将一个新学生元组(学号:121200,姓名:陈东,性别:男,所在系:IS,年龄:18岁)插入student表中
insert into student(sno,sname,ssex,sdept,sage) values (‘121200’,‘陈冬’,‘男’,‘IS’,18);
若有属性,而没有对应的值要写NULL(赋空值)
(2)插入子查询结果
insert into 表名(属性1,属性2…)子查询
例:对每一个系,求学生的平均年龄,并把结果存入数据库
先建一个新表,一列存放系名,另一列存放学生平均年龄create table dept_age (sdept char(15) Avg_age SMALLINT);按系分组求平均年龄,把系名和平均年龄存入表中
insert into dept_age(sdept,Avg(age)select sdept,Avg(sage) from student group by sdept);
(1)update 表名 set 属性(修改的值)where 条件
例:将学生201200的年龄改为22岁
update student set sage=22 where sno=‘201200’;
(2)带子查询的修改 IN
例:将计算机科学系全体学生成绩置0.
两个不同的表,先找在计算机科学系的学生学号,然后再将学号置为0
update sc set grade=0 where sno IN (select sno from student where sdept=‘CS’);
(1)delect from 表名 where 条件
例:删除学号为201200的学生记录
delete from student where sno=‘201200’;
(2)带子查询的删除语句IN
例:删除计算机科学系所有学生的选课记录
两个不同的表,先找在计算机科学系的学生学号,然后再将选计算机科学的学号删除
delete from sc where sno IN (select sno from student where sdept=‘CS’);
四、视图
create view 视图名(属性1,属性2)//属性可省 as 查询语句 [with check option] //可省,加上表示对视图进行插入、删除操作时要保证更新插入或删除的行满足子查询中的条件表达式
例:建立信息系学生的视图
create view IS_Student AS select sno,sname,sage from student where sdept=‘IS’;
例:建立信息系学生的视图,并要求进行修改和插入操作时仍需保证该视图只有信息系学生
create view IS_Student AS select sno,sname,sage from student where sdept=‘IS’ with check option;
drop view 视图名 [cascade] //[cascade] 可省,表示级联删除该视图和它导出的所有视图
例:删除视图BT_S
drop view BT_S;
例:在信息系学生的视图中找出年龄小于20岁的学生
select sno,sage from IS_Student where Sage<20;
例:将信息系学生视图IS_Student 中学号为“201215” 的学生姓名改为“刘辰”;
update IS_student set sname=‘刘辰’ where sno=‘201215’;