众所周知,存储过程只是在第一次进行编译,以后直接可以调用。在做项目时,碰到使用存储过程的机会太多了,今天就来总结下我在写存储过程的一些心得体会。
个人认为,写存储过程的时候只要能把握住两个要点基本上就没啥大问题了。
1.游标
2.动态sql语句
对于游标,遵循如下的流程:
1. 定义游标:create _cursorName cursor for …
2. 打开游标 :open _cursorName
3. 进行循环:while @@fetch_status=0
4. 关闭游标:close _cursorName
5. 释放游标:deallocate _cursorName
平时开发中比较头疼的就是动态sql的问题,动态sql有两种执行方式:使用execute执行、使用exec sp_executesql执行.
其中第二种方式可以灵活的设置输入输出参数,推荐使用。下面举个例子。
Declare @par nvarchar(500)
Declare @sql nvarchar(500)
Declare @nid varchar(10)
Declare @nworkid varchar(10)
Set @nworkid = 8888
set @sql = 'select @id = agentid from tblagentinfo where workid = @workid'
Set @par = '@id varchar(10) output,@workid varchar(10)'
exec sp_executesql @sql,@par,@nid output,@nworkid
Print convert(varchar(10),@nid)
其中@par中的变量顺序要和后面执行时候变量的参数顺序一致,也就是说输出参数在前面,输入参数在后面。且@par必须是Unicode或可以隐式转换为ntext的字符串常量、变量
上面一段代码的意思是:根据@nworkid的值查询出对应的@id值,并打印出来。
这两种执行动态sql的方式,据网上说第二种的效率比第一种高,本人没有进行测试。
如果写一个复杂的存储过程,将上面两点都把握住后,无非就是再加些判断之类的条件语句。
下面做个实例。
需求:将每个公司对应的号码更新到pone和ptwo字段
declare @com1 varchar(500)
declare @sql nvarchar(1024)
declare @par nvarchar(1024)
declare @id varchar(10)
declare @one varchar(500)
declare @phone varchar(20)
declare @flag int
declare _pp cursor for select one from result
open _pp
fetch next from _pp into @com1
set @flag = 0
while @@fetch_status = 0
begin
set @sql = 'select @id1 = id,@one1=one from result where one = @com2'
set @par = '@id1 int output,@one1 varchar(500)output,@com2 varchar(1024)'
exec sp_executesql @sql,@par,@id output,@one output,@com1
if charindex('.',@one) <> 0
begin
set @phone = reverse(left(ltrim(reverse(@one)),7))
if @flag = 0
begin
update result set pone = @phone where id = @id-1
set @flag = 1
end
else
begin
update result set ptwo = @phone where id = @id-2
set @flag = 0
end
end
fetch next from _pp into @com1
end
close _pp
deallocate _pp
可能到现在还没说存储过程怎么写,其实存储过程无非就是上面的内容,然后加上定义语句:create _procName proc
上面的代码在mssqlserver2005下测试通过。