存储过程、sp_executesql存储过程、try catch错误处理

原文出自:http://blog.csdn.net/sqlserverdiscovery/article/details/7851881


存储过程就是把一个或多个T-SQL语句组合到一个逻辑单元中,在SQL Server数据库中保存为一个对象。在创建完成后,定义会保存在sys.sql_modules系统目录视图中。

存储过程的有点:

1、存储过程是在数据层汇集的T-SQL代码,可以促进代码的重复使用,同时有助于调试、寻找bug。也就是说这些代码就存放在数据库里,而不是嵌入在应用程序中的SQL代码,再由这些代码连接起来,最后发送到服务器上来执行的。

2、存储过程相对于大的即席查询,能够减少网络流量。

3、存储过程则更安全,因为内嵌的即席查询容易进行SQL注入。

4、相对于函数、视图,存储过程能使用流控制、临时表、表变量等。

5、可以淡化数据获取的方法。一旦底层的表有变化,不用去修改嵌入到应用程序中的sql代码,只要修改存储过程就可以了。

6、存储过程的查询响应时间比较稳定。存储过程提供了更加可靠的查询计划缓存,因此可以重用,而即席查询完全依赖于执行计划被缓存的环境(语句中的参数)。

另外,需要注意的:'CREATE/ALTER PROCEDURE'不允许将数据库名称指定为对象名前缀

[sql]  view plain copy
  1. --1.1创建无参数存储过程  
  2. --这个存储过程的定义很像视图定义  
  3. create procedure dbo.usp_wct  
  4. as  
  5.   
  6. select wcId,  
  7.        wcV,  
  8.        wcDate  
  9. from wcT  
  10. go  
  11.   
  12. --1.2执行存储过程  
  13. exec dbo.usp_wct  
  14.   
  15.   
  16.   
  17. --2.1创建带参数的存储过程  
  18. create procedure dbo.usp_param_wct  
  19. (@wcId bigint =1,        --默认值为1  
  20.  @wcDate datetime =null--默认值为null  
  21. as  
  22.   
  23. select wcV  
  24. from dbo.wcT  
  25. where wcId = @wcId  
  26.       and isnull(@wcDate,1)=case when @wcdate is null  
  27.                                       then 1   
  28.                                  else wcDate  
  29.                             end  
  30.   
  31. --返回状态值,一般不用于返回计算结果,而是用来返回表明存储过程执行的状态        
  32. return 1   
  33.   
  34. go  
  35.   
  36.   
  37. --2.2.1调用存储过程  
  38. exec dbo.usp_param_wct '1','2012-07-01'  
  39.   
  40. --2.2.2调用存储过程,带参数名  
  41. exec dbo.usp_param_wct @wcid='1',  
  42.                        @wcdate='2012-07-01'  
  43.   
  44. --2.2.3调用存储过程,带参数名,只输入一个参数值,另一个会使用默认值  
  45. exec dbo.usp_param_wct @wcid='1'  
  46.   
  47. --2.2.4调用存储过程,带参数名,不输入参数,2个参数都会使用默认值  
  48. exec dbo.usp_param_wct   
  49.   
  50.   
  51.   
  52. --3.1创建带output参数的存储过程  
  53. create procedure dbo.usp_output_param_wct  
  54. (@wcId bigint =1,            --默认值为1  
  55.  @wcDate datetime =null,     --默认值为null  
  56.  @wcV varchar(50) output)    --输出参数,用来返回计算结果  
  57. as  
  58.   
  59. select @wcV = wcV  
  60. from dbo.wcT  
  61. where wcId = @wcId  
  62.       and isnull(@wcDate,1)=case when @wcdate is null  
  63.                                       then 1   
  64.                                  else wcDate  
  65.                             end  
  66.   
  67. --返回状态值,一般不用于返回计算结果,而是用来返回表明存储过程执行的状态        
  68. return 1   
  69.   
  70. go  
  71.   
  72.   
  73. --3.2调用存储过程  
  74. declare @output varchar(50)  
  75.   
  76. exec dbo.usp_output_param_wct @wcId =1,         --输入参数  
  77.                               --@wcDate = null,  
  78.                               @wcv = @output output       --输出参数,存放返回值  
  79.   
  80. print @output    
  81.   
  82.   
  83.   
  84. --4.1修改存储过程  
  85. create procedure dbo.usp_output_param_wct  
  86. (@wcId bigint =1,            --默认值为1  
  87.  @wcDate datetime =null,     --默认值为null  
  88.  @wcV varchar(50) output)    --输出参数,用来返回计算结果  
  89. with encryption --加密存储过程  
  90. as  
  91.   
  92. select @wcV = wcV  
  93. from dbo.wcT  
  94. where wcId = @wcId  
  95.       and isnull(@wcDate,1)=case when @wcdate is null  
  96.                                       then 1   
  97.                                  else wcDate  
  98.                             end  
  99.   
  100. --返回状态值,一般不用于返回计算结果,而是用来返回表明存储过程执行的状态        
  101. return 1   
  102.   
  103. go        
  104.   
  105. --4.2查看定义  
  106. select object_name(object_id),  
  107.        definition                --显示为NULL  
  108. from sys.sql_modules  
  109. where object_id = object_id('dbo.usp_output_param_wct')   
  110.   
  111.   
  112.   
  113. --5.在SQL Server启动时自动执行存储过程  
  114. create procedure dbo.create_table    
  115. as  
  116.    select * into wc.dbo.wcX  
  117.    from wc.dbo.wcT  
  118. go  
  119.   
  120. --5.1设置为true,在SQL Server启动时自动执行存储过程  
  121. exec sp_procoption @procname   = 'dbo.create_table',  
  122.                    @optionname = 'startup',  
  123.                    @optionvalue= 'true'  
  124.                      
  125. --5.2设置为false来禁止  
  126. --只有dbo拥有的master数据库中的对象才能更改启动设置。  
  127. use master  
  128. go  
  129.   
  130. exec sp_procoption @procname   = 'dbo.create_table',  
  131.                    @optionname = 'startup',  
  132.                    @optionvalue= 'false'  
  133.   
  134.   
  135.   
  136. --6.1每次存储过程执行时都重新编译  
  137. --需要注意的是:当表、索引数据大量更新时,会进行语句级别的重新编译  
  138. create procedure dbo.usp_backupset_info  
  139. (@startDate datetime,  
  140.  @finishDate datetime)  
  141. with recompile     --不保存执行计划,每次都是重新编译  
  142. as  
  143.   
  144. select SUM(backup_size)/1024/1024/1024 as 'GB'  
  145. from msdb.dbo.backupset  
  146. where backup_start_date >= @startDate  
  147.       and backup_finish_date <= @finishDate  
  148.       and type = 'D'  --数据库备份,不是日志备份或差异备份  
  149. go  
  150.   
  151.   
  152. --6.2清空过程缓存  
  153. select *  
  154. from sys.dm_exec_cached_plans  
  155.   
  156. dbcc freeproccache      --清空过程缓存  
  157.   
  158. --再次查询发现都已经清空  
  159. select *  
  160. from sys.dm_exec_cached_plans  
  161.   
  162.   
  163.   
  164. --7.刷新存储过程,查看元数据  
  165. exec sp_refreshsqlmodule @name ='dbo.usp_output_param_wct'  
  166.   
  167. select p.name,           --存储过程名称  
  168.        p.object_id,  
  169.          
  170.        pp.parameter_id,     
  171.        pp.name,          --参数名称  
  172.        pp.default_value, --好像不起作用  
  173.        t.name            --参数列的类型  
  174. from sys.procedures p  
  175. inner join sys.parameters pp  
  176.         on pp.object_id = p.object_id  
  177. inner join sys.types t  
  178.         on t.system_type_id = pp.system_type_id  
  179. where p.object_id =965578478  
  180.   
  181.   
  182. --8.删除存储过程  
  183. DROP PROCEDURE dbo.usp_output_param_wct  
  184.               

存储过程的Execute as选项
 

[sql]  view plain copy
  1. --1.创建表  
  2. create table dbo.wcE  
  3.     (vid int not null primary key clustered,  
  4.      v int not null  
  5.     )  
  6.   
  7. insert into dbo.wcE  
  8. values(1,100),  
  9.       (2,200),  
  10.       (3,300)  
  11.   
  12.   
  13. --2.创建存储过程,存储过程的架构与存储过程中引用对象的架构一样  
  14. create procedure dbo.usp_delete_wcE  
  15. as  
  16.   
  17. delete from dbo.wcE  
  18. go  
  19.   
  20.   
  21. --3.1创建登录名  
  22. create login wclogin with password = 'wclogin123'  
  23.   
  24.   
  25. --3.2创建数据库用户  
  26. create user wclogin  
  27.   
  28.   
  29.   
  30. --4.授予用户执行存储过程的权限  
  31. grant exec on dbo.usp_delete_wcE to wclogin   
  32.   
  33. grant connect  to wclogin  
  34.   
  35.   
  36.   
  37. /*====================================================  
  38. 5.1打开另一个客户端,以wclogin登录名登进去,然后执行存储过程,  
  39. 虽然这个用户没有访问存储过程中所引用表的权限,  
  40. 但是由于存储过程的架构与存储过程中引用对象的架构一样,  
  41. 同时由于存储过程中只能是insertupdatedeleteselect,  
  42. 而不能是trancate等操作,这就是所有权链,所以没有报错.  
  43.   
  44. 特别需要注意的是:以上的所有权链对于动态的SQL是无效的.  
  45. ======================================================*/  
  46. exec dbo.usp_delete_wcE  
  47.   
  48. --5.2这里改为truncate后,会报错  
  49. alter procedure dbo.usp_delete_wcE  
  50. as  
  51.   
  52. truncate table dbo.wcE  
  53. go  
  54.   
  55.   
  56.   
  57. --6.1使用execute as owner指定存储过程的任何调用,  
  58. --都是在存储过程架构的拥有者的安全上下文运行的  
  59. --这时再次以wclogin登录就可以执行存储过程而不会报错  
  60. alter procedure dbo.usp_delete_wcE  
  61. with execute as owner  
  62. as  
  63.   
  64. truncate table dbo.wcE  
  65. go  
  66.   
  67.   
  68. --6.2以执行用户的权限来执行存储过程  
  69. --在以wclogin登录执行时会报错  
  70. alter procedure dbo.usp_delete_wcE  
  71. with execute as caller  
  72. as  
  73.   
  74. truncate table dbo.wcE  
  75. go  
  76.   
  77. --6.3以创建或最近一次更新存储过程的用户的权限来执行存储过程,  
  78. --在以wclogin登录执行时会报错  
  79. alter procedure dbo.usp_delete_wcE  
  80. with execute as self  
  81. as  
  82.   
  83. truncate table dbo.wcE  
  84. go  
  85.   
  86.   
  87. --6.4以指定的用户的权限来执行存储过程,  
  88. --在以wclogin登录执行时显然不会报错  
  89. alter procedure dbo.usp_delete_wcE  
  90. with execute as 'dbo'  
  91. as  
  92.   
  93. truncate table dbo.wcE  
  94. go  
  95.   
  96.   
  97.   
  98. --6.5这个存储过程用了动态的SQL语句  
  99. create procedure dbo.w  
  100. as  
  101.   
  102. exec('select * from dbo.wcE');  
  103. go  
  104.   
  105. grant exec on dbo.w to wclogin  
  106.   
  107.   
  108. --在客户端以wclogin登录,执行时会报错  
  109. --拒绝了对对象'wcE'(数据库'wc',架构'dbo')的SELECT权限。  
  110. exec dbo.w  

 

 

[sql]  view plain copy
  1. --1.函数  
  2. if exists(select * from sys.objects where name = 'f_splitSTR' and type = 'tf')  
  3.    drop function dbo.f_splitSTR  
  4. go  
  5.   
  6. create function dbo.f_splitSTR  
  7. (  
  8.     @s varchar(8000),     --要分拆的字符串  
  9.     @split varchar(10)    --分隔字符  
  10. )   
  11. returns @re table(                      --要返回的临时表  
  12.                      col varchar(1000)  --临时表中的列   
  13.                  )  
  14. as  
  15. begin     
  16.   declare @len int  
  17.     
  18.   set @len = LEN(@split)      --分隔符不一定就是一个字符,可能是2个字符  
  19.     
  20.   while CHARINDEX(@split,@s) >0  
  21.   begin  
  22.     insert into @re   
  23.     values(left(@s,charindex(@split,@s) - 1))  
  24.       
  25.     set @s = STUFF(@s,1,charindex(@split,@s) - 1 + @len ,'')    --覆盖:字符串以及分隔符  
  26.   end  
  27.     
  28.   insert into @re values(@s)  
  29.     
  30.   return   --返回临时表  
  31. end  
  32. go    
  33.   
  34.   
  35. select * from dbo.f_splitSTR('123,456',',')  
  36.   
  37.   
  38.   
  39. --2.存储过程  
  40.   
  41. --创建类型  
  42. create type var_orgid as table  
  43. (  
  44. org_id numeric(10,0)  
  45. )  
  46.   
  47. --创建存储过程  
  48. create proc usp_orgid  
  49. @orgid_table var_orgid readonly  
  50. as  
  51.   
  52. select * from @orgid_table  
  53. go  
  54.   
  55.   
  56. --定义表变量  
  57. declare @orgid_table as var_orgid  
  58.   
  59. insert into @orgid_table   
  60. values(123)  
  61.   
  62. exec usp_orgid @orgid_table  


 sp_executesql存储过程,可以使动态语句重用,提高效率:

[sql]  view plain copy
  1. DECLARE @sumcount INT  
  2. DECLARE @tmpSQL NVARCHAR(1000)  
  3. DECLARE @TABLENAME  VARCHAR(50)  
  4. SELECT @TABLENAME = ' sys.objects ' --表名变量赋值  
  5.   
  6. SELECT @tmpSQL = 'select @sum = convert(varchar(50),count(object_id)) from ' + @TABLENAME   
  7.   
  8.   
  9. /*  
  10. 参数1: 动态语句  
  11. 参数2:定义的参数,这个参数就是在动态语句中引用到的变量@sum  
  12. 参数3:指明了执行结果@sum的值,放到@sumcount参数里面,  
  13.   
  14. 这里需要特别注意的是,动态语句中的变量,和外面定义的变量,是不同的,  
  15. 下面的语句,实际相当于:  
  16.   
  17. declare @sum int   
  18.   
  19. select @sum = convert(varchar(50),count(object_id))   
  20. from  + 表名   
  21.   
  22. 所以,通过sp_executesql,可以把语句产生的结果输出到外面的变量,  
  23. 这样我们才能知道输结果  
  24. */  
  25. exec sp_executesql @tmpsql,  
  26.                    N'@sum int output',  
  27.                    @sumcount out  
  28.   
  29. select @sumcount  

try catch 错误处理

[sql]  view plain copy
  1. create proc proc_t(@i int)  
  2. as  
  3.   
  4. select 5 * 1.0 / @i  
  5. go  
  6.   
  7.   
  8. --1.不会报错  
  9. begin try  
  10.     begin tran  
  11.         exec proc_t 1  
  12.         select '执行成功'  
  13.     commit tran  
  14. end try  
  15. begin catch  
  16.   select '执行失败'  
  17.   if @@trancount >0   
  18.      rollback  
  19. end catch  
  20.   
  21.   
  22. --2.这次会报错,因为分母为0  
  23. begin try  
  24.     begin tran  
  25.         exec proc_t 0  
  26.         select '执行成功'  
  27.     commit tran  
  28. end try  
  29. begin catch  
  30.   select '执行失败'  
  31.   if @@trancount >0   
  32.      rollback  
  33. end catch  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值