SQL Server 练习二(基础)

一、前言

每周一练,又接触到了一些深奥(于我而言)的查询语句。简单的多表连接查询,嵌套查询(子查询),集合查询以及数据更新。互相学习,不排除所学有限,仍有最优解或正解的情况,所以也希望得到各路大佬的指点。

二、准备

1.连接查询

主要分为三种:内连接、外连接、交叉连接。

  • 1.1 内连接
    内连接是最典型,最常用的连接查询,它根据表中共同的列来进行匹配,只有符合条件才能查询出来。通常两个表存在主外键关系时会使用到内连接查询。 常使用"="比较运算符来判断两列数据是否相等,通过使用关键字INNER JOIN 进行表之间的关联。根据所使用的比较方式不同,内连接分为等值连接、自然连接和自连接三种。
  • 1.2 外连接
    在内连接中只有满足连接条件的元组才能作为结果输出。但有时希望输出那些不满足连接条件的元组信息,这就需要使用外连接。外连接可分为左外连接、右外连接、完全外连接。
    1)左外连接(LEFT JOIN 或 LEFT OUTER JOIN)
    左外连接包含LEFT JOIN左表所有行,如果左表中某行在右表没有匹配,则结果中对应行右表的部分全部为空(NULL)。
    2)右外连接(RIGHT JOIN 或 RIGHT OUTER JOIN)
    右外连接包含RIGHT JOIN右表所有行,如果右表中某行在左表没有匹配,则结果中对应行左表的部分全部为空(NULL)。
    3)完全外连接(FULL JOIN 或 FULL OUTER JOIN)
    完全外连接包含FULL JOIN左右两表中所有的行,如果右表中某行在左表没有匹配,则结果中对应行左表的部分全部为空(NULL),如果左表中某行在右表没有匹配,则结果中对应行右表的部分全部为空(NULL)。如果表之间有匹配行,则整个结果集行包含基表的数据值。

因此使用外连接时表的顺序很重要。

  • 1.3交叉连接
    交叉连接就是表之间没有任何关联事件,查询将返回左表中的每一行与右表中的所有行组合,相当于两个表相乘。没有WHERE子句的交叉联接相当于表的笛卡尔积。

2.嵌套查询

  • 2.1使用in的子查询
    先进行内部查询,然后再进行外部查询
    通过in(not in)引入的子查询结果是包含零个值或多个值的列表。子查询返回结果之后,外部查询将利用这些结果。
  • 2.2用ANY,SOME,ALL修改的比较运算符
    可以用 ALL或 ANY 关键字修改引入子查询的比较运算符。SOME是与 ANY 等效的ISO标准。
    以“>”比较运算符为例,>ALL表示大于每一个值。换句话说它表示大于最大值。
    例如,>ALL(1,2,3)表示大于3。>ANY表示至少大于一个值,即大于最小值。因此>ANY (1,2,3)表示大于1。
    若要使带有>ALL的子查询中的行满足外部查询中指定的条件,引入子查询的列中的值必须大于子查询返回的值列表中的每个值。
    同样,>ALL表示要使某一行满足外部查询中指定的条件,引入子查询的列中的值必须至少大于子查询返回的值列表中的一个值。
  • 2.3使用exists的子查询
    使用exists关键字引入子查询后,子查询的作用就相当于进行存在测试。外部查询的WHERE子句测试子查询返回的行是否存在。子查询实际上不产生任何数据,它只返回true或false值。
    注意,使用exists引入的子查询在下列方面与其他子查询不同:
    exists关键字前面没有列名,常量或其他表达式。
    由exists引入的子查询的选择列表通常几乎都是由星号(*)组成的。由于只是测试是否存在子查询中指定条件的行,因此不必列出列名。

3.集合查询

多个select语句的查询结果可以进行集合操作,包括并(union),交(intersect),差(except).前提是select语句必须要有相同数量的列,且类型兼容。其中并运算有 union 和 union all 两种用法。前者自动去掉重复元组,后者保留重复元组。

4.数据更新

  • 1.插入数据
  • 2.更新数据
  • 3.删除数据

三、练习

1.创建练习题目的数据库(新建查询)

create database 练习二
go 
use 练习二
go

create table student(
	sno char(10) primary key,
	sname char(20) not null,
	ssex char(2) check (Ssex in ('男','女')) not null,
	smajor char(20) not null,
	sdept char(20) not null,
	sage tinyint not null,
)
go 

insert student (sno, sname, ssex,smajor,sdept,sage) values('J001','艾伦','男','计算机科学与技术','计算机科学学院',19)
insert student (sno, sname, ssex,smajor,sdept,sage) values('J002','三笠','女','计算机科学与技术','计算机科学学院',18)
insert student (sno, sname, ssex,smajor,sdept,sage) values('J003','阿尔敏','男','计算机科学与技术','计算机科学学院',19)
insert student (sno, sname, ssex,smajor,sdept,sage) values('D001','路飞','男','临床医学','医学院',20)
insert student (sno, sname, ssex,smajor,sdept,sage) values('D002','艾斯','男','临床医学','医学院',21)
insert student (sno, sname, ssex,smajor,sdept,sage) values('D003','萨博','男','临床医学','医学院',20)
insert student (sno, sname, ssex,smajor,sdept,sage) values('D004','娜美','女','口腔医学','医学院',22)
insert student (sno, sname, ssex,smajor,sdept,sage) values('D005','罗宾','女','口腔医学','医学院',21)
insert student (sno, sname, ssex,smajor,sdept,sage) values('R001','鸣人','男','播音','艺术学院',21)
insert student (sno, sname, ssex,smajor,sdept,sage) values('R002','雏田','女','编导','艺术学院',20)
insert student (sno, sname, ssex,smajor,sdept,sage) values('R003','佐助','男','编导','艺术学院',21)
insert student (sno, sname, ssex,smajor,sdept,sage) values('R004','卡卡西','男','播音','艺术学院',25)
insert student (sno, sname, ssex,smajor,sdept,sage) values('M001','柯南','男','社工','法学院',19)
insert student (sno, sname, ssex,smajor,sdept,sage) values('M002','灰原哀','女','社工','法学院',19)
insert student (sno, sname, ssex,smajor,sdept,sage) values('M003','基德','男','社工','法学院',20)
insert student (sno, sname, ssex,smajor,sdept,sage) values('M004','波本','男','社工','法学院',25)
insert student (sno, sname, ssex,smajor,sdept,sage) values('M005','秀一','男','法学','法学院',23)
go

create table course(
	cno char(10) primary key,
	cname char(30) not null,
	ccredit tinyint check (ccredit>=1 and ccredit<=10) not null 
 )
go

insert course(cno, cname, ccredit) values ('A001','数据库及应用',3.5)
insert course(cno, cname, ccredit) values ('A002','离散数学',3)
insert course(cno, cname, ccredit) values ('A003','人体结构',4)
insert course(cno, cname, ccredit) values ('A004','高等数学',4)
insert course(cno, cname, ccredit) values ('A005','大学英语',2)
insert course(cno, cname, ccredit) values ('A006','民法典',4)
insert course(cno, cname, ccredit) values ('A007','播音主持教材',3)
insert course(cno, cname, ccredit) values ('A008','思想道德',3.5)
insert course(cno, cname, ccredit) values ('A009','军事理论',1)
go

create table sc(
	sno char(10) not null,
	cno char(10) not null,
	grade numeric(3, 0)check (grade>=0 and grade<=100),
	primary key(sno,cno),
	foreign key(sno)references student(sno),
	foreign key(cno)references course(cno)
)
go

insert sc (sno,cno,grade) values ('J001','A001',95)
insert sc (sno,cno,grade) values ('J001','A008',85)
insert sc (sno,cno,grade) values ('J002','A001',91)
insert sc (sno,cno,grade) values ('J002','A002',85)
insert sc (sno,cno,grade) values ('J002','A009',88)
insert sc (sno,cno,grade) values ('D001','A002',90)
insert sc (sno,cno,grade) values ('D001','A008',45)
insert sc (sno,cno,grade) values ('D002','A002',85)
insert sc (sno,cno,grade) values ('D003','A005',86)
insert sc (sno,cno,grade) values ('D004','A001',91)
insert sc (sno,cno,grade) values ('R001','A003',80)
insert sc (sno,cno,grade) values ('R001','A005',92)
insert sc (sno,cno,grade) values ('R003','A003',83)
insert sc (sno,cno,grade) values ('R003','A005',78)
insert sc (sno,cno,grade) values ('R004','A006',48)
insert sc (sno,cno,grade) values ('M001','A008',90)
insert sc (sno,cno,grade) values ('M001','A009',85)
insert sc (sno,cno,grade) values ('M002','A008',79)
insert sc (sno,cno,grade) values ('M002','A004',80)
insert sc (sno,cno,grade) values ('M003','A006',90)
insert sc (sno,cno,grade) values ('M003','A003',86)
insert sc (sno,cno,grade) values ('M004','A001',92)
insert sc (sno,cno,grade) values ('M004','A002',null)
insert sc (sno,cno,grade) values ('M005','A003',null)
go

建好的表如下:

  • student表
    在这里插入图片描述

  • sc表
    在这里插入图片描述

  • course表
    在这里插入图片描述

2.练习题

1.新建查询时注意是在 ‘练习二’ 数据库中
2.我们在敲完之后可以自我检验看语法是否通过
3.在执行语句后,如果不确定答案,在符合现实的情况下,可以看看基表,自己比对比对,人工找一下符合条件的结果。如果要查看表的内容,选中要看的表,右键编辑前200行即可。
4.可能数据库跟不上你的速度,刷新即可,有时候已经打开了一个表,当更新了数据后,刷新后也没变化,叉掉打开的表,重新打开这张表就好。
5.对于一些数据更新的题目,建议单独搞一个表练手,对新表进行操作。

在这里插入图片描述
在这里插入图片描述

2.1多表连接查询(使用JOIN)

  • 1.查询学生的选课情况,要求显示学号、姓名、课程号。
-- 涉及到两个表有同一个属性时,要区分开来,不然会说不明确。
select student.sno,sname,cno
from student join sc
on student.sno = sc.sno

在这里插入图片描述

  • 2.查询‘法学院’学生的修课情况,要求列出学生的名字、所修课的课程号和成绩。
select sname,cno,grade 
from student join sc
on student.sno = sc.sno 
where sdept = '法学院'

在这里插入图片描述

  • 3.查询计算机科学学院修了‘数据库及应用’课程的学生的修课成绩,要求列出学生姓名、课程名和成绩。
-- 三个表及以上时后面接着 join ...on...就行了
select sname,cname,grade 
from student join sc on student.sno = sc.sno 
join course on course.cno = sc.Cno
where sdept = '计算机科学学院' and cname = '数据库及应用'

在这里插入图片描述

  • 4.查询所有修了‘军事理论’课程的学生的修课情况,要求列出学生姓名和所在的院系。(多表的连接)
select sname,sdept
from student join sc on student.sno = sc.sno
join course on course.cno = sc.cno
where cname = '军事理论'

在这里插入图片描述

  • 5.查询学生的修课情况,包括修了课程的学生和没有修课的学生,要求显示学号、姓名、课程号。
-- 主要是一个左外连接,因为要求查询包括未修课程的学生在内,需要列出左表(student表)中所有符合搜索条件的数据行。
select student.sno,sname,cno
from student  left join sc on student.sno = sc.sno 

在这里插入图片描述

  • 6.查询哪些学生没有选课,要求列出学号、姓名和所在系。
select student.sno,sname,sdept
from student  left join sc on student.sno = sc.sno 
where sc.sno is null 

在这里插入图片描述

2.2嵌套查询(子查询)

  • 7.用子查询查询与‘路飞’在同一个院系的学生。
select *
from student 
where sdept in (
	select sdept
	from student
	where sname = '路飞'
	)

在这里插入图片描述

  • 8.用子查询找出平均成绩为大于80分的学生的学号、姓名、院系。
select student.sno,sname,sdept
from student,sc
where student.sno = sc.sno 
group by student.sno,sname,sdept
having avg(grade) >= 80

在这里插入图片描述

  • 9.用子查询查询选修了“思想道德”课程的学生的学号、姓名。
select student.sno,sname
from student,sc
where student.sno = sc.sno and sc.cno in(
	select cno
	from course
	where cname = '思想道德'
	)

在这里插入图片描述

  • 10.用子查询查询修了‘A008’课程且成绩高于此课程的平均成绩的学生的学号和成绩。
select sno,grade 
from sc 
where cno = 'A008' and grade > (
	select avg(grade) 
	from sc
	where cno = 'A008'
)

在这里插入图片描述

  • 11.查询医学院考试成绩最高的学生的学号。
select student.sno
from student,sc
where student.sno = sc.sno and sdept = '医学院'and sc.grade >= all(
	select grade
	from student,sc 
	where student.sno = sc.sno and sdept = '医学院'
	)

在这里插入图片描述
-12.用子查询查询没有选修‘A003’号课程的学生姓名和所在系。

select sname,sdept 
from student 
where sno not in(
	select student.sno
	from sc,student 
	where sc.cno='A003'and Student.Sno= sc.Sno
	)

在这里插入图片描述

  • 13.用子查询找出‘柯南’所选课程的学分之和。
在这里插入代码片select sum(ccredit)学分之和
from course,sc
where  course.cno = sc.cno and sc.sno in(
	select sno
	from student 
	where sname = '柯南'
)

在这里插入图片描述

  • 14.用子查询找出所有学生中年龄最大的学生的姓名、年龄。
select sname,sage
from student
where sage >= all(
	select sage 
	from student 
	)	

在这里插入图片描述

  • 15.用子查询找出所有没有成绩的学生的姓名及系别。
select sname,sdept 
from sc,student 
where sc.grade is null and Student.Sno= sc.Sno

在这里插入图片描述

  • 16.用子查询统计‘法学院’每位学生的平均成绩。
select sno,avg(grade)平均成绩
from sc
where  sc.sno in(
	select sno
	from student 
	where sdept = '法学院'
)
group by sno

在这里插入图片描述

2.3集合查询

  • 17.查询‘法学院’的学生和年龄不大于20岁的学生。
select *
from student 
where sdept = '法学院'
union
select *
from student
where sage <= 20

在这里插入图片描述

  • 18.查询‘法学院’且年龄不大于20岁的学生。
select *
from student 
where sdept = '法学院'
intersect
select *
from student
where sage <= 20

在这里插入图片描述

  • 19.查询‘法学院’的学生与年龄不大于20岁的学生的差集。
select *
from student 
where sdept = '法学院'
except
select *
from student
where sage <= 20

在这里插入图片描述

2.4数据更新(修改,删除,添加)

  • 1、新来了一个同学(学号:C001;姓名:李舜生;性别:男;年龄:22;所在系:法学院;专业:法学)的记录插入到学生表中,并增加相应的选课记录(C001,A007)。
insert into student (sno,sname,ssex,smajor,sdept,sage) values('C001','李舜生','男','法学','法学院',22)
go
insert into sc (sno,cno)values('C001','A007')
  • 2、将所有学生的年龄增加1岁。
update student set sage = sage + 1
  • 3.发现基德同学考试替考,将其所有成绩改为0分。
update sc 
set grade = 0
from sc 
inner join student 
on sc.sno = student.sno
where sname = '基德'
  • 4.学号为“D001”的学生平时表现优异,将其“A002”成绩增加20分。
update sc 
set grade = grade + 20
from sc 
inner join student 
on sc.sno = student.sno
where student.sno = 'D001'

在这里插入图片描述

因为我们在创建这个表的时候就成绩中添加了约束条件 取值范围是1 - 100,此时D001的成绩已经是90分,再加20分就爆表了。个人感觉反过来讲也可以防止我们犯错。

  • 5.学号为“D001”的学生由于退学,删除该学生及其选课记录。
-- 注意这里不能颠倒删除顺序。
delete 
from sc
where sno = 'D001'
go
delete 
from student
where sno = 'D001'

猜你喜欢

转载自blog.csdn.net/m0_51086313/article/details/110896485