--维护数据库--
--存储过程(procedure)--
--概述:
SQl Serve的存储过程是由一个或多个T-SQL语句组成的一个集合。常用的程序代码段通常被创建成存储过程,一次创建多次调用,这样既简化程序员的工作也减少与服务器交互的网络通信流量。存储过程中可以包含数据库中执行操作的程序语句,也包括调用其他过程。存储过程可以接收和输出参数,向调用它的程序返回值。存储过程被调用后,会返回给调用它的程序状态值,以表明调用成功或者调用失败以及调用失败的原因。
--使用存储过程的优点:
1)减少网络流量。在客户端和服务器的交互中,T-SQL语言中的每个代码行在执行时都是要利用网络发送的,代码被封装成存储过程,只有对执行存储过程语句的调用时才会利用网络发送。
2)增强安全性。在客户端和服务器之间调用存储过程时,只有执行存储过程的语句是可见的,用户无法看到或访问到存储过程所涉及的数据库对象,便无法破坏这些对象,使用为存储过程加密也能保障存储过程的安全。
3)提升编程效率。存储过程对常用代码的封装采用了消除重复代码的编写操作,降低代码的不一致性,并允许拥有权限的用户访问和执行代码,提升代码编程效率。
4)提高执行效率。系统默认下,只有首次执行存储过程时需要编译存储过程,创建一个执行计划,今后在执行该存储过程时则无需在编译,节省程序处理时间,提高执行效率。如果存储过程引用的数据发生变化明,也无需重新编写存储过程,系统提供了重新编译存储过程来帮助存储过程正确执行。
--分类:(在SQL Server 中存储过程分为用户自定义存储过程、系统存储过程和拓展存储过程三种类型)
1)用户自定义存储过程。该存储过程封装了用户所需的功能代码,可以单纯实现一段程序代码,可以通过输入参数接收用户输入的值(带输入参数的存储过程),可以使用输出参数将存储过程执行后的结果返回给调用它的语句(带输出参数的存储过程)。
2)系统存储过程。以sp_开头的存储过程是系统存储过程。是系统封装好的程序代码。例如:sp_helptext表示查看数据库对象信息;sp_helpindex表示查看表中索引信息。
3)拓展存储过程。以xp_开头的存储过程是拓展存储过程。由系统提供,用来在SQL Server和外部程序之间提供一个接口,以实现各种系统的维护活动。例如:xp_loogininfo表示返回Windows用户和Windows组的相关信息。
--存储过程管理:
--存储过程的创建和执行(注:创建存储过程的语句要存在于同一个批处理中。)
--不带参数的存储过程
♦创建:
create procedure 存储过程名 --create procedure命令表示创建存储过程,procedure允许只写前四个字母proc。
[with encryption] --with encryption是可选项,可以为存储过程的创建文本加密。
[with recompile] --with recompile是可选项,使存储过程在执行时不保存执行计划,在每次执行时重新编译,以防止覆盖已存在于内存中的执行计划。
as
T-SQL语句
例:(创建名为“p_客户信息表_地址”的存储过程,用来实现在“商品管理数据库”的“客户信息表”中查询“辽宁沈阳”的客户信息)
use 商品管理数据库
go
select*from 客户信息表 where 地址='辽宁沈阳' --创建前可以先查询一下要封装的记录
use 商品管理数据库
go
create proc p_客户信息表_地址 --创建存储过程
as
select*from 客户信息表 where 地址='辽宁沈阳'
♦执行:
execute 存储过程名 --execute表示执行存储过程,可以简写exec。
例:
use 商品管理数据库
go
exec p_客户信息表_地址
--带参数的存储过程(带输入参数的存储过程 和 带输出参数的存储过程)
--1)带输入参数的存储过程
♦创建:
create procedure 存储过程名 --create procedure命令表示创建存储过程,procedure允许只写前四个字母proc。
@参数名 数据类型[(长度)] [, ......] --参数名,应声明在as之前
[with encryption] --with encryption是可选项,可以为存储过程的创建文本加密。
[with recompile] --with recompile是可选项,是存储过程在执行时不保存执行计划,在每次执行时重新编译,以防止覆盖已存在于内存中的执行计划。
as
T-SQL语句
例:(创建名为“p_客户信息表_地址x”的存储过程,用来实现在“商品管理数据库”的“客户信息表”中查找指定地址的客户信息)
use 商品管理数据库
go
create proc p_客户信息表_地址x
@address nvarchar(30)
as
select*from 客户信息表 where 地址=@address
♦执行:
execute 存储过程名 [@参数名=] 参数值 [, ...] --“参数值”的数据类型必须与被赋值参数的数据类型兼容
例:(执行存储过程“P_客户信息表_地址x”,查找出地址“辽宁沈阳”的客户信息)
use 商品管理数据库
go
exec p_客户信息表_地址x @address='辽宁沈阳'
exec p_客户信息表_地址x '辽宁大连' --省略参数名
--2)带输出参数的存储过程
♦创建:
create procedure 存储过程名 --create procedure命令表示创建存储过程,procedure允许只写前四个字母proc。
[@参数名 数据类型[(长度)][ , ...... , ] ]
@参数名 数据类型[(长度)] output [ , ...... ]
[with encryption]
[with recompile]
as
T-SQl语句
--允许创建只带输入参数的存储过程,也允许创建既带输出参数又带输入参数的存储过程。输出参数要在声明参数后加上output关键字来指明。通常再被封装在存储过程中的T-SQL语句中为输出参数赋值。
例:(创建名为“p_客户信息表_姓名”的存储过程,将查询“客户信息表”中客户编号为20130001的客户信息姓名,并将客户姓名赋值给一个输出参数的查询代码封装到该存储过程中)
create proc p_客户信息表_姓名
@name nvarchar(5) output
as
set @name=(select 客户姓名 from 客户信息表 where 客户编号='20130001')
--select @name=客户姓名 from 客户信息表 where 客户编号='20130001'
♦执行:
declare @参数名 数据类型[(长度)][, ...] --首先使用declare命令声明执行过程中所涉及的参数,包括输入参数和输出参数
[set @参数=值1] ... --如果使用了输入参数,用set语句为输入参数赋值
execute 存储过程名 [@参数[, ... ,]] @参数 output [, ...]
例:(执行名为“p_客户信息表_姓名”的存储过程,要求将查询“客户信息表”中的客户编号为20130001的客户姓名显示出来)
use 商品管理数据库
go
declare @name nvarchar(5)
exec p_客户信息表_姓名 @name output
print '客户编号为20130001的客户姓名为:'+@name
例:带输入参数的存储过程、带输出参数的存储过程 的创建和执行的总例:(创建名为“p_客户信息表_编号_姓名”的存储过程,要求将查询“客户信息表”中指定客户编号的客户姓名显示出来。并执行存储过程查看结果)
create proc p_客户信息表_编号_姓名
@num nchar(8),@name nvarchar(5) output --定义了一个输入参数@num和一个输出参数@name,数据类型和取值范围与“客户信息表”中的“客户编号”字段和“客户姓名”字段一致
as
select @name=客户姓名 from 客户信息表 where 客户编号=@num use 商品管理数据库
go
declare @num nchar(8),@name nvarchar(5) --定义了@num和@name两个用来与存储过程中的参数传递和接收值。
set @num='' --使用set命令为变量@num赋值,以便将值传给输入参数@num。
exec p_客户信息表_编号_姓名 @num,@name output --exec执行存储过程时按顺序将两个变量带入到存储过程中。
print '客户编号为'+@num+'的客户的姓名为:'+@name --print语句使用了字符串连接运算,输出详细结果。
理解例子
--查看存储过程
注:可以使用系统存储过程sp_helptext、sp_help和sp_depends查看存储过程的创建信息和创建文本。
exec 系统存储过程 用户自定义存储过程名
说明:sp_helptext显示被查看的存储过程的创建文本信息,创建时被加密的存储过程的创建文本信息不能被查看。
sp_help显示被查看的而存储过程的所有者、类型、创建时间及包含哪些参数等信息。
sp_depends显示被查看的存储过程所关联的数据表和字段信息。
例:
use 商品管理数据库
go
exec sp_depends p_客户信息表_姓名
exec sp_help p_客户信息表_姓名
exec sp_helptext p_客户信息表_姓名
--修改存储过程
注:在管理数据库过程中,可以根据需要修改已创建的用户自定义存储过程。对于已经加密的存储过程,不能使用管理器方式修改其内容,拥有权限的用户可以使用T-SQl语言修改其创建内容,同时将加密属性去掉,当实质上是删除原来的加密的存储过程,重新创建一个新的存储过程,使用时须谨慎使用。
alter procedure 存储过程名 ---alter命令表示修改,“存储过程名”必须是已存在的用户自定义的存储过程。procedure允许只写前四个字母proc。
[@参数名 数据类型[(长度)][, ... ,]] @参数名 数据类型[(长度)] output [, ......]
[with encryption]
[with recompile]
as
T-SQL语句
例:(将名为“p_客户信息表_姓名”的存储过程 的功能修改为查找客户编号为20130003的客户信息,并将结果传递给一个参数)
use 商品管理数据库
alter proc p_客户信息表_姓名
@name nvarchar(5) output
as
set @name=(select 客户姓名 from 客户信息表 where 客户编号='20130003')
--删除存储过程
注:对于不再使用的存储过程可以将其删除,以节省磁盘空间。删除存储过程不会对它所涉及的数据表等数据库对象产生影响,但调用它的语句再次使用时会产生错误。
drop procedure 存储过程名 --drop 命令表示删除命令,可以删除加码和不加密的存储过程,删除时并没有确认是否删除的提示,需谨慎使用。procedure允许只写前四个字母proc。
例:(删除名为“p_进货信息表_商品编号”的已加密的存储过程)
use 商品管理数据库
go
drop proc p_进货信息表_商品编号
--重编译存储过程
注:由于存储过程执行一次后会把编译过程记录到内存中,当再次执行同一个存储过程时则无需编译而直接执行。随着用户对系统的操作,数据库中的数据随时可能发生变化,如果变化涉及了存储过程所关联的数据表,那么存储过程需要重新编译,以得到正确的执行结果。重新编译存储过程有三种方法。
1)创建存储过程的同时重新编译
create procedure 存储过程名
with recompile --with recompile命令使存储过程在执行时不保存执行计划,在每次执行时重新编译,以防止覆盖已存在于内存中的执行计划。
as
T-SQL语句
2)执行存储过程的同时重新编译
exec 存储过程名 with recompile --在执行存储过程的同时使用with recompile语句,可以使存储过程在执行时重新编译。
3)使用命令方式预设存储过程重新编译
exec sp_recompile 存储过程名 --可以为已创建的存储过程预设重新编译,即从预设语句执行结束后,下一次执行存储过程时为存储过程重新编译。
例:(使用系统存储过程sp_recompile为存储过程“p_客户信息表_姓名”预设重新编译)
use 商品管理数据库
go
exec sp_recompile 'P_客户信息表_姓名'
注:"--"可看成说明或者注释文本