一、本文列举了一些T-SQL存储过程和触发的例题以及解答
背景知识:
一、存储过程:封装了可重用的代码块和模块,通过接收参数然后返回结果集来执行。存储过程经过数据库编译后存储在服务器端。
二、触发器:由SQL自动执行,当发生特定操作(update、delete、insert)时自动执行事前编辑好的代码块。原理是使用两个临时表inserted、deleted进行操作。
二、名称解释(不区分大小写)
- student学生表:
- 包含属性列:sno学号、sname学生姓名、age年龄、sex性别、dno学院编号、birthday生日
- sc选课信息表:
- 包含属性列:sno学号、cno课程号、grade成绩
- dept学院信息表:
- 包含属性列:dno学院编号、dname学院名称、dean学院负责人
- course课程信息表:
- 包含属性列:cno课程号、cname课程名称、tname老师名称、credit学分、room教室
下面语句可以直接复制到SQL Server运行
方法不唯一,有问题欢迎留言讨论!代码块见文章末尾
运行时注意:由于函数、视图等必须是批处理语句中仅有的语句,可能需要单独创建SQL文件。
且变量命名不可重复,需要运行请自行创建新的SQL文件。
- 运行方法,选中需要执行的语句
三、代码
–创建一个按名字模糊查询学生基本信息的存储过程
create procedure check_name(@sname varchar(20))
as
select sno,sname,age,dno from student where sname like @sname
–执行
exec check_name ‘王%’–创建一个依据学生学号返回其所有课程平均分的存储过程 student_average
create procedure student_average(@sno char(8))
as
return(select avg(grade) from sc where sno = @sno)
–执行
DECLARE @no char(8) ,@avg float
SET @no=‘20002059’
EXEC @avg=student_average @no
PRINT CONVERT(CHAR(10),@avg)
SELECT SNAME ,@avg AS ‘平均分’ FROM student WHERE SNO=@no–创建一个执行插入功能的存储过程,可以向 chengjiao 表中插入一条学生记录,该存储过程包含三个参数,分别表示学生学号、学生姓名、学生出生日期,其中学生出生日期参数默认值为’1990-1-1’。
create procedure insert_proc(@sno varchar(8),@sname varchar(8),@date datetime = ‘1909-1-1’)
as
insert into chengjiao(sno,sname,birthday) values(@sno,@sname,@date)
–执行
EXEC INSERT_chengjiao ‘20081001’, ‘jiang’
EXEC INSERT_chengjiao ‘20081002’,‘jiang’,‘1991-12.1’–创建一个存储过程,可以根据指定的学生学号,通过参数返回该学生的姓名和所选课程的平均分。
create procedure check_avg(@sno char(8))
as
select sname,avg(grade) from student,sc where sc.sno = student.sno and student.sno = @sno
group by sname,student.sno–存储过程在执行后都会返回一个整型值。如果成功执行,返回 0;否则,返回-1----99之间的数值。下例根据例 3 创建的存储过程,判断该存储过程是否执行成功。
DECLARE @x Int
exec @x=INSERT_chengjiao ‘20082001’, ‘jiang’
PRINT @x --输出-4,不能执行成功,因为原表中已经有了该学号,违反了主码的唯一性–创建触发器,要求在学生表中删除一个学生时,同时从选课表中将其所有选课信息删除
create trigger on_delete on student
for delete
as
delete from sc
where sc.sno in (select sno from deleted)–创建触发器限定一个学生最多只能选择 4 门课
create trigger select_four on sc
for insert
as
declare @count int
set @count = (select count(*) from sc where sno in (select sno from inserted))
if @count >= 5
begin
rollback
print(‘选课超过四门,不可再选’)
end–利用触发器限定修改后的分数只能比原来高
create trigger high_than_before on sc
for update
as
–利用count来记录是否有超过原来的分数的
if(select count(*) from sc where grade > (select grade from deleted)) = 0
begin
rollback
print(‘插入后的分数不可以比原来的分数低’)
end–(1)创建一个存储过程 del_course,根据指定课程号删除 course 表中的相应记录。
create procedure del_course (@cno char(8))
as
delete from course
where cno = @cno–(2)在表 DEPT 上创建一个触发器 depart_update,当更改学院编号时,同步更改 student表中的学院编号。
create trigger depart_update on dept
for update
as
update student
–先从inserted表中获取更新值
set dno = (select dno from inserted)
–条件是当前的dno与被删除的dno相同
where dno in (select dno from deleted)–(3)对课程 course 表创建触发器限定一个教师一学期最多只能上 2 门课
create trigger teach on course
for insert
as
declare @count int
set @count = (select count(*) from course where cno in (select cno from inserted))
if @count > 2
begin
rollback
print(‘只能上两门课’)
end–(4)创建一个存储过程,可以根据指定的教师名,通过参数返回该教师所上课程的门数及平均分。
create procedure count_avg(@tname char(8))
as
return select course.cno,count(distinct course.cname) as ‘课程数’,avg(grade) from sc,course where course.cno = sc.cno and tname = @tname group by course.cno–(5)创建一个按教师名查询教师上课信息的存储过程
create procedure check_lesson(@tname char(20))
as
select * from course where tname = @tname–(6)创建一个按部门查询学生信息的存储过程
create procedure check_student_info(@dno char(8))
as
select * from student where dno = @dno
四、SQL代码块
--创建一个按名字模糊查询学生基本信息的存储过程
create procedure check_name(@sname varchar(20))
as
select sno,sname,age,dno from student where sname like @sname
--执行
exec check_name '王%'
--创建一个依据学生学号返回其所有课程平均分的存储过程 student_average
create procedure student_average(@sno char(8))
as
return(select avg(grade) from sc where sno = @sno)
--执行
DECLARE @no char(8) ,@avg float
SET @no='20002059'
EXEC @avg=student_average @no
PRINT CONVERT(CHAR(10),@avg)
SELECT SNAME ,@avg AS '平均分' FROM student WHERE SNO=@no
--创建一个执行插入功能的存储过程,可以向 chengjiao 表中插入一条学生记录,该存储过程包含三个参数,分别表示学生学号、学生姓名、学生出生日期,其中学生出生日期参数默认值为'1990-1-1'。
create procedure insert_proc(@sno varchar(8),@sname varchar(8),@date datetime = '1909-1-1')
as
insert into chengjiao(sno,sname,birthday) values(@sno,@sname,@date)
--执行
EXEC INSERT_chengjiao '20081001', 'jiang'
EXEC INSERT_chengjiao '20081002','jiang','1991-12.1'
--创建一个存储过程,可以根据指定的学生学号,通过参数返回该学生的姓名和所选课程的平均分。
create procedure check_avg(@sno char(8))
as
select sname,avg(grade) from student,sc where sc.sno = student.sno and student.sno = @sno
group by sname,student.sno
--存储过程在执行后都会返回一个整型值。如果成功执行,返回 0;否则,返回-1----99之间的数值。下例根据例 3 创建的存储过程,判断该存储过程是否执行成功。
DECLARE @x Int
exec @x=INSERT_chengjiao '20082001', 'jiang'
PRINT @x --输出-4,不能执行成功,因为原表中已经有了该学号,违反了主码的唯一性
--创建触发器,要求在学生表中删除一个学生时,同时从选课表中将其所有选课信息删除
create trigger on_delete on student
for delete
as
delete from sc
where sc.sno in (select sno from deleted)
--创建触发器限定一个学生最多只能选择 4 门课
create trigger select_four on sc
for insert
as
declare @count int
set @count = (select count(*) from sc where sno in (select sno from inserted))
if @count >= 5
begin
rollback
print('选课超过四门,不可再选')
end
--利用触发器限定修改后的分数只能比原来高
create trigger high_than_before on sc
for update
as
--利用count来记录是否有超过原来的分数的
if(select count(*) from sc where grade > (select grade from deleted)) = 0
begin
rollback
print('插入后的分数不可以比原来的分数低')
end
--(1)创建一个存储过程 del_course,根据指定课程号删除 course 表中的相应记录。
create procedure del_course (@cno char(8))
as
delete from course
where cno = @cno
--(2)在表 DEPT 上创建一个触发器 depart_update,当更改学院编号时,同步更改 student表中的学院编号。
create trigger depart_update on dept
for update
as
update student
--先从inserted表中获取更新值
set dno = (select dno from inserted)
--条件是当前的dno与被删除的dno相同
where dno in (select dno from deleted)
--(3)对课程 course 表创建触发器限定一个教师一学期最多只能上 2 门课
create trigger teach on course
for insert
as
declare @count int
set @count = (select count(*) from course where cno in (select cno from inserted))
if @count > 2
begin
rollback
print('只能上两门课')
end
--(4)创建一个存储过程,可以根据指定的教师名,通过参数返回该教师所上课程的门数及平均分。
create procedure count_avg(@tname char(8))
as
return select course.cno,count(distinct course.cname) as '课程数',avg(grade) from sc,course where course.cno = sc.cno and tname = @tname group by course.cno
--(5)创建一个按教师名查询教师上课信息的存储过程
create procedure check_lesson(@tname char(20))
as
select * from course where tname = @tname
--(6)创建一个按部门查询学生信息的存储过程
create procedure check_student_info(@dno char(8))
as
select * from student where dno = @dno