任务描述
本关任务:学习 SQLServer 中存储过程的创建和使用。
相关知识
存储过程提供了很多 T-SQL 语言没有的高级特性,其传递参数和执行逻辑的能力,为处理各种复杂任务提供了支持。并且,由于存储过程是经过编译后,存储在服务器上的,这减少了执行过程中的传输带宽和执行时间。相反,如果使用 T-SQL ,则每次需要经过传输,再编译和执行。
什么是存储过程
存储过程是 SQLServer 中一个非常重要的数据库对象,它实际是一组为了完成特定功能的 T-SQL 语句集合。存储过程经编译后,存储在数据库中,用户通过指定存储过程的名称,并给出相应的参数,就可以对其进行执行。
SQLServer 中的存储过程具有如下特点:
存储过程不同于函数,存储过程不返回取代其名称的值,也不能直接在表达式中使用。
存储过程的类型
SQL Server 包含多种可用的存储过程,主要包括用户定义存储过程、扩展存储过程和系统存储过程。
用户定义存储过程
存储过程是指封装了可重用代码的模块或者例程。存储过程可以接收输入参数、向客户端返回表格或者标量结果和消息、调用数据定义语言( DDL )和数据操作语言( DML ),然后返回输入参数。 在 SQL Server 中,用户定义的存储过程有两种类型,即 T-SQL 和 CLR 。
扩展存储过程
扩展存储过程以在 SQL Server 环境外执行的动态链接库( DLL )来实现。扩展存储过程通过前缀 xp_ 来标识,它们以与系统存储过程相似的方式来执行。
系统存储过程
系统存储过程主要存储在 master 数据库中,并以 sp_ 为前缀,并且系统存储过程主要是从系统表中获取信息,从而为系统管理员 SQL Server 提供支持。通过系统存储过程, SQL Server 中的许多管理性或者信息性的活动,都可以被顺利有效地完成。
创建存储过程
在 SQL Server 中,使用 CREATE PROCEDURE 语句创建存储过程,具体的语法格式如下所示。
CREATE { PROC | PROCEDURE } procedure_name [ ; number ]
[ { @parameter data_type }
[ VARYING ] [ = default ] [ OUT | OUTPUT ] [READONLY]
[ WITH {RECOMPILE|ENCRYPTION|RECOMPILE,ENCRYPTION}]
[ FOR REPLICATION ]
AS { [ BEGIN ] sql_statement [;] [ ...n ] [ END ] }
简单介绍个参数的含义。
在命名自定义存储过程时,尽量不要使用 sp_ 作为名称前缀,避免与系统存储过程冲突。如果指定的名称与系统存储过程相同,由于系统存储过程优先级高,那么自定义的存储过程永远也不会执行。
创建简单存储过程
从 studentdb 数据库中获取学生学号、姓名和性别的存储过程。语句如下所示:
CREATE PROCEDURE proc_getInfos
AS
BEGIN
SELECT sno '学号', sname '姓名', sex '性别' frome student
END
创建带计算函数的存储过程
统计 studentdb 数据库中,男同学个数的存储过程。语句如下:
CREATE PROCEDURE proc_count_male
AS
BEGIN
SELECT COUNT(*) AS '男同学' frome student where sex='男'
END
创建带输入参数的存储过程
根据用户输入的姓名,得到相应的信息的存储过程。语句如下:
CREATE PROCEDURE proc_select_where
@name varchar(50)
AS
BEGIN
SELECT * from student where sname=@name
END
创建带输出参数的存储过程
创建一个存储过程,根据用户输入的年龄,返回大于输入年龄的学生有多少。语句如下:
CREATE PROCEDURE proc_select_ret
@age int,
@age_count int output
AS
BEGIN
SELECT @age_count=COUNT(*) from student where age>@age
END
执行存储过程
在 SQL Server 中,可以使用 EXEC 或 EXECUTE 语句执行存储过程。
执行不带参数的存储过程
EXEC proc_getInfos
执行带参数的存储过程
EXEC proc_select_where '张三'
执行带输入输出参数的存储过程
DECLARE @age_ int=19;
DECLARE @count int;
EXEC proc_select_ret @age_, @count output
select '该班一共有'+LTRIM(STR(@count))+'人年龄大于'+LTRIM(STR(@age_));
编程要求
我们已经为你建好了数据库与数据表,并添加了相应的数据内容。 你只需:
表 student 的字段类型除了 birthday 是 date 类型,其余均为 varchar 类型,表内容如下:
测试说明
本关涉及到的测试文件是 step1.sh ,平台将运行用户补全的 step1.sql 文件,得到数据,然后执行以下操作:
将得到的数据与答案比较,判断程序是否正确;
如果操作正确,你将得到如下的结果:
开始你的任务吧,祝你成功!
实验代码
USE studentdb
go
SET NOCOUNT ON
go
--********** create proc_student_info **********--
--********** Begin **********--
create proc proc_student_info
as
begin
select * from student
end
--********** End **********--
go
exec proc_student_info
go
--********** create proc_sno **********--
--********** Begin **********--
create proc proc_sno
@sno varchar(50)
as
begin
select * from student where sno=@sno
end
--********** End **********--
go
exec proc_sno '1001'
go
--********** create proc_add **********--
--********** Begin **********--
create proc proc_add
@sno varchar(50),
@sname varchar(50),
@sex varchar(10),
@date date,
@dis varchar(50),
@school varchar(50)
as
begin
if EXISTS(SELECT * FROM student WHERE sno=@sno)
print 'Already have a primary key '+@sno
else
insert into student values(@sno,@sname,@sex,@date,@dis,@school)
end
--********** End **********--
go
exec proc_add '1004','HMM','female','2019-6-2','English','national school'
go
exec proc_student_info
go
--********** create student_del **********--
--********** Begin **********--
CREATE PROC student_del
@sno varchar(50)
as
begin
if EXISTS(select * from student where sno=@sno)
begin
delete from student where sno=@sno
print 'successfully deleted'
end
else
print 'No such student'
end
--********** End **********--
go
exec student_del '1001'
go
exec proc_student_info
go