朋友们,我们在写SQL Server的存储过程时,最担心的莫过于存储过程执行中出现错误,有些语句生效了、而有些语句却没有执行。这其实就是SQL Server的事务处理问题了,我们之所以写成存储过程,一般都是希望能够将所有语句执行一起提交的,那如何保证SQL Server事务的一致性呢?
我下面结合我的经验给大家一个比较完美的解决方案。
Set XAct_Abort ON 语句
当 SET XACT_ABORT 为 ON 时,如果执行 Transact-SQL 语句产生运行时错误,则整个事务将终止并回滚。当 SET XACT_ABORT 为 OFF 时,有时只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。如果错误很严重,那么即使 SET XACT_ABORT 为 OFF,也可能回滚整个事务。OFF 是默认设置。
所以,在您的存储过程中,一定要在存储过程的最开始写上一句Set XAct_Abort ON。语法很简单:
Set XAct_Abort ON
SET NOCOUNT ON 语句
当 SET NOCOUNT 为 ON 时,将不给客户端发送存储过程中的每个语句的 DONE_IN_PROC 信息。如果存储过程中包含的一些语句并不返回许多实际的数据,则该设置由于大量减少了网络流量,因此可显著提高性能。
所以,在您的存储过程中,最好最开始写上一行:SET NOCOUNT ON。语法很简单:
SET NOCOUNT ON
begin tran ... commit tran
需要纳入事务的语句,开头必须写上begin tran表示事务开始,最后协商commit tran表示事务提交。begin tran 和 commit tran之间的语句,就是处于同一个事务处理的语句。
对应的语法如下:
set xact_abort on set nocount on begin tran update ... insert ... delete ... ... commit tran
通过 @@error 判断是否出错
在每一个执行语句之后,都要判断语句执行是否出错,如果错误则进跳转到错误处理。语法如下:
if @@error<>0 begin set @error='xxxxx出错!' goto l_err --跳出的标签 end
整体结构示例
下面用一个例子说明整体架构:
CREATE procedure myproc @myval1 int, @myval2 int, @myresult int output, @error nvarchar(100) output as declare @mytest int begin set xact_abort on set nocount on begin tran set @error=space(0) update ... if @@error<>0 begin set @error='更新出错!' goto l_err --跳出 end insert ... if @@error<>0 begin set @error='插入出错!' goto l_err --跳出 end delete ... if @@error<>0 begin set @error='删除出错!' goto l_err --跳出 end set @mytest=@myval1+@myval2 set @myresult =@mytest set xact_abort off --重置 commit tran l_err:begin --错误跳转 rollback tran --事务回滚 end
执行就很简单了:
declare @myresult int declare @error nvarchar(100) exec MyProc 100,200,@myresult,@error
希望对您有所帮助!