王珊数据库课程实验(游标、触发器、存储过程)

本文使用的教材是王珊主编的《数据库原理》。实验环境是SQL Server 2017

实验数据:

20121521	张勇	男	24	CS
20121522	刘晨	女	20	CS
20121523	王敏	女	19	MA
20121525	张立	男	20	IS
20121526	刘个	女	20	CS



1	数据库	5	4
2	数学	NULL	2
3	信息系统	1	4
4	操作系统	6	3
5	数据结构	7	4
6	数据处理	NULL	2
7	C语言	NULL	4
8	DB_Design	NULL	1


20121521	1	0
20121521	2	0
20121521	3	0
20121522	2	0
20121522	3	0

数据库创建及第三章的查询语句

/*
create table Student(
	Sno char(8) primary key,
	Sname varchar(20) unique,
	Ssex char(2),
	Sage int,
	Sdept varchar(50)
);

*/

/*
create table Course(
	Cno varchar(10) primary key,
	Cname varchar(30) not null,
	Cpno varchar(10),
	CCredit int,
	foreign key(Cpno) references Course(Cno)
);
*/

/*
create table SC(
	Sno char(8),
	Cno varchar(10),
	Grade int,
	primary key(Sno,Cno),
	foreign key(Sno) references Student(Sno),
	foreign key(Cno) references Course(Cno)
);
*/

/*
select Sno,Sname
from Student;
*/

/*
select Sname,Sno,Sdept
from Student;
*/

/*
select *
from Student;
*/

/*
select Sname,2018-Sage as Birth
from Student;
*/

/*
select Sname,lower(Sdept)
from Student;
*/

/*
select distinct Sno
from SC;
*/

/*
select Sname
from Student
where Sdept='CS'
*/

/*
select Sname,Sage
from Student
where Sage<20;
*/

/*
select Sno,grade
from SC
where grade not between 80 and 85;
*/

/*
select Sname,Ssex
from Student
where Sdept in ('CS','MA');
*/

/*
select Sname,Sno,Ssex
from Student
where Sname like '_晨%';
*/

/*
select *
from Course
where Cname like 'DB\_%i__' escape '\';
*/

/*
select *
from SC
where grade is not null;
*/

/*
select Sno,Grade
from SC
where Cno='3'
order by grade desc;
*/


/*
select *
from Student
order by Sdept asc,Sage desc;
*/

/*
select count(*)
from Student;
*/

/*
select count(distinct Sno)
from SC;
*/

/*
select avg(grade)
from SC
where Cno='1';
*/

/*
select max(grade)
from SC
where Cno='1';
*/

/*
select sum(CCredit)
from Course,SC
where SC.Cno=Course.Cno and SC.Sno='20121521';
*/

/*
select Cno,count(Sno) as 'Count(Sno)'
from SC
group by Cno;
*/

/*
select Sno
from SC
group by Sno
having count(Cno)>2;
*/

/*
select Sno,avg(grade)
from SC
group by Sno
having avg(grade)>80;
*/

/*
select *
from Student,SC
where Student.Sno =SC.Sno;
*/

/*
select SC.Sno,Sname
from Student,SC
where Student.Sno=SC.Sno and
	SC.Cno='2' and SC.Grade>60;
*/

/*
select C1.Cno,C2.Cpno
from Course as C1,Course C2
where C1.Cno=C2.Cno and C2.Cpno is not null
order by Cno;
*/

/*
--外连接
select SC.Sno,SC.Grade
from Student right outer join SC on(Student.Sno=SC.sno);
*/

/*
select Student.Sno,Student.Sname,Course.Cname,SC.Grade
from Student,SC,Course
where Student.Sno=SC.Sno and SC.Cno=Course.Cno;
*/

/*
select Sno,Sname,Sdept
from Student
where Sdept in(
	select Sdept
	from Student
	where Sname='刘晨'
);
*/

/*
select S1.Sno,S1.Sname,S1.Sdept
from Student as S1,Student as S2
where S2.Sname='刘晨' and S1.Sdept=S2.Sdept;
*/

/*
select Student.Sno,Student.Sname
from Student,SC,Course
where Student.Sno=SC.Sno and SC.Cno=Course.Cno and Course.Cname='信息系统';
*/

/*
select Sno,Cno
from SC as SC1
where SC1.Grade>(
	select avg(Grade)
	from SC as SC2
	where SC1.Sno=SC2.Sno
);
*/


/*
select Sname,Sage
from Student 
where Sdept!='CS' and
	Sage(
	select count(Cno)
	from Course
	)
;
*/

--3.63
/*
select SC1.Sno
from SC as SC1
where not exists(
	select *
	from SC as SC2
	where SC2.Sno='201215122' and
		not exists(
			select *
			from SC as SC3
			where SC1.Sno=SC3.Sno and 
				SC2.Sno=SC3.Sno
		) 	
)
;
*/

/*
select *
from Student
where Sdept='CS' and Sage<=19;
*/

/*
select *
from Student
where Sdept='CS'
intersect
select *
from Student
where Sage<=19
;
*/

/*
select *
from SC
where Cno='1'
union
select *
from SC
where Cno='2'
;
*/

/*
select *
from Student
where Sdept='CS'
except
select *
from Student
where Sage<=19
;

select *
from Student
where Sdept='CS' and Sage>19;

*/

/*
select Sname
from Student,(select Sno from SC where Cno='1') as SC1
where Student.Sno=SC1.Sno;
*/

/*
insert into Student
values('20121528','陈冬','男',18,'IS');
*/

/*
create table Dept_age(
	Sdept varchar(50),
	Avg_age int,
);
*/

/*
insert into Dept_age(Sdept,Avg_age)
select Sdept,avg(Sage)
from Student
group by Sdept;
*/

/*
update student
set Sage=23
where Sno='20121521';
*/

/*
update student
set Sage+=1;
*/

/*
update SC
set grade=0
where Sno in(
	select Sno
	from Student
	where Sdept='CS'
);
*/

/*
delete from Student
where Sno='20121528';
*/


--alter table SC add Term date;

--没有能创建断言
/*
create assertion assse_sc_cnum2
	check(60>=all(select count(*) from SC group by Cno,SC.Term));
*/

触发器实验

触发器(1):在没有外键约束的情况下,在sc表中插入student表中不存在的学号及在course表中不存在的课程,会报错,并不让插入

create trigger sc_insert on SC
for insert
as
begin
if exists(select Sno from inserted where Sno not in (select Sno from Student))
print 'not Sno'
          delete 
          from SC
          where Sno not in(select Sno from Student)
if exists (select Cno from inserted where Cno not in(select Cno from Course))
print 'not Cno'
         delete from SC
         where Cno not in(select Cno from Course)
end;

王珊数据库课程实验(游标、触发器、存储过程)_第1张图片
王珊数据库课程实验(游标、触发器、存储过程)_第2张图片

触发器(2):为course表创建一个触发器c_del,当删除了course表中的一条课程信息时,同时将表sc表中相应的学生选课记录删除掉。
当前的SC表如下:
王珊数据库课程实验(游标、触发器、存储过程)_第3张图片

创建触发器:
create trigger c_del on course
for delete
as
begin
delete from sc where cno in (select cno from deleted);
end;

王珊数据库课程实验(游标、触发器、存储过程)_第4张图片

删除课程号为2的课程:
delete from course where cno='2';

王珊数据库课程实验(游标、触发器、存储过程)_第5张图片
执行上面的删除语句后,sc表如下:
王珊数据库课程实验(游标、触发器、存储过程)_第6张图片

存储过程

1、创建一个名为stu_pr的存储过程
该存储过程能查询出计算机系学生的所有资料,包括学生的基本信息、学生的选课信息(含未选课同学的信息)。要求在创建存储过程前请判断该存储过程是否已创建,若已创建则先删除,并给出“已删除!”信息,否则就给出“不存在,可创建!”的信息。

1)先判断是否已经存在存储过程stu_pr:

if exists(select name from sysobjects where name = 'stu_pr')
	begin
		drop procedure stu_pr
		print '已删除'
	end
else
	print '不存在,可创建'

王珊数据库课程实验(游标、触发器、存储过程)_第7张图片

2)创建存储过程stu_pr:

create procedure stu_pr
	as
		select student.*, sc.cno,sc.grade,sc.term 
	from Student left outer join sc on Student.Sno=SC.Sno;

王珊数据库课程实验(游标、触发器、存储过程)_第8张图片

3)执行存储过程stu_pr

execute stu_pr;

王珊数据库课程实验(游标、触发器、存储过程)_第9张图片
2、创建带参数的存储过程
练习:创建一个名为stu_proc1的存储过程,查询某系、某姓名的学生的学号、姓名、年龄,选修课程名、成绩。系名和姓名在调用该存储过程时输入,其默认值分别为“%”与“李%”。执行该存储过程,用多种参数加以测试。

本题的坑点是:默认值是模糊匹配,如果一直想用等号那就大错特错了,困扰我很久,应该用like!!!

create procedure stu_proc1 @dept varchar(50)='%',@name varchar(20)='李%'
	as
		select student.sno,Student.Sname,Student.Sage,Course.Cname,sc.Grade
		from student left outer join sc on student.sno=sc.sno
		left outer join course on sc.cno=course.cno
		where student.Sdept like @dept and Student.Sname like @name

王珊数据库课程实验(游标、触发器、存储过程)_第10张图片

测试:
execute stu_proc1;

王珊数据库课程实验(游标、触发器、存储过程)_第11张图片


测试:
execute stu_proc1 @dept='CS',@name='Tom'

王珊数据库课程实验(游标、触发器、存储过程)_第12张图片
3、创建带输出参数的存储过程
创建一个名为Course_sum的存储过程,可查询某门课程考试的总成绩。总成绩可以输出,以便进一步调用。

create procedure Course_sum @course_name varchar(30),@total_grade int output
	as 
		set @total_grade=(select sum(sc.grade) 
							from course left outer join sc on course.cno=sc.cno
							where @course_name=course.Cname)

王珊数据库课程实验(游标、触发器、存储过程)_第13张图片

declare @total int
execute course_sum '数据库',@total output	--千万不要少了这个output
select @total

王珊数据库课程实验(游标、触发器、存储过程)_第14张图片

游标实验

(1) 创建游标,逐行显示Student表的记录,并用WHILE结构来测试@@Fetch_Status的返回值。输出格式如下:
‘学生编号’+’-----’+学生姓名’+’----’+‘院系’+’-----’+‘总学分’’

declare stu cursor
	for
	select Student.Sno as '学生编号',Student.Sname as '学生姓名',Student.Sdept as '院系',sum(Course.CCredit) as '总学分'
	from Student left outer join SC on Student.Sno=SC.Sno
	left outer join Course on SC.Cno=Course.Cno
	group by Student.Sno,Student.Sname,Student.Sdept
open stu
fetch next from stu
while(@@FETCH_STATUS=0)
	fetch next from stu
close stu

王珊数据库课程实验(游标、触发器、存储过程)_第15张图片
(2) 利用游标和存储过程,要求将(授课课程数处于前三名的教师)的信息,输出格式如下:

=============授课数最多的三位教师的信息================
教师编号	         教师姓名	        总授课数		    所在院系
create procedure rank_cursor @rank_cursor cursor varying output
as
	set @rank_cursor=cursor forward_only static for
		select Course.t_id as '教师编号',Course.cteacher '教师姓名',count(Course.Cno) '总授课数',Student.Sdept '所在院系'
		from Course left outer join sc on course.cno=sc.cno
		left outer join Student on sc.sno=student.sno
		group by Course.t_id,course.cteacher,student.Sdept
		order by count(course.cno) desc
		open @rank_cursor

王珊数据库课程实验(游标、触发器、存储过程)_第16张图片

declare @info varchar(100)
set @info='=============授课数最多的三位教师的信息================'
select @info
declare @my_cursor cursor
exec rank_cursor @rank_cursor=@my_cursor output
fetch next from @my_cursor --这里执行了第一次
declare @i int
set @i=2
while(@@FETCH_STATUS=0)
	while(@i>=1)
		begin
			fetch next from @my_cursor
			set @i=@i-1
			print 'ok'
			if(@i=0)
				begin
					close my_cursor
					deallocate my_cursor
					return	
				end
					
		end
 

王珊数据库课程实验(游标、触发器、存储过程)_第17张图片

你可能感兴趣的:(数据库基础知识)