新增文章
文章标题
分类
C#
云星空
K3 BOS
K3 功能
用友
Oracle
python
SQL
MySql
PHP
HTML
script
windows
Access
影视后期
财务
服务
生活
内容
drop table dbo.test go create table dbo.test ( ID int, UserID int, Name varchar(100) ) go --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- 父过程如下: drop procedure aTran_1 go create procedure aTran_1 @ID BIGINT, @UserID BIGINT, @Name varchar(50) as declare @tranCount int ; set @tranCount = ( select @@tranCount ) ; print '执行【begin tran】 进入 父事务前 全局 @@tranCount = ' + cast( @tranCount as varchar(50) ) -- 执行【begin tran】 进入 父事务前 全局 @@tranCount = 0 begin tran ; set @tranCount = ( select @@tranCount ) ; print '执行【begin tran】 进入 父事务后 全局 @@tranCount = '+ cast( @tranCount as varchar(50) ) -- 执行【begin tran】 进入 父事务后 全局 @@tranCount = 1 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- 调用 第2层事务 declare @result int ; exec @result = aTran_2 @ID = @ID, @UserID = @UserID, @Name = @Name ; print '执行【exec @result = aTran_2 ... 】 执行 子事务后 @result = '+ cast( @result as varchar(50) ) ; -- 执行【exec @result = aTran_2 ... 】 执行 子事务后 @result = 3 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- IF ( @result != 3 ) begin set @tranCount = ( select @@tranCount ) ; print '执行【rollBack tran】 回滚 父事务前 全局 @@tranCount = '+ cast( @tranCount as varchar(50) ) -- 进入 父事务后 全局 @@tranCount = 1 rollBack tran ; set @tranCount = ( select @@tranCount ) ; print '执行【rollBack tran】 回滚 父事务后 全局 @@tranCount = '+ cast( @tranCount as varchar(50) ) -- return ; end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- commit tran ; set @tranCount = ( select @@tranCount ) ; print '执行【commit tran】 提交 父事务后 全局 @@tranCount = '+ cast( @tranCount as varchar(50) ) -- 提交 父事务后 全局 @@tranCount = 0 go --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- 子存储过程如下: --内层事务存储过程,演示如何处理才能在嵌套的事务存储过程中正确处理事务 drop procedure aTran_2 go create procedure aTran_2 @ID BIGINT , @UserID BIGINT , @Name varchar(50) as begin declare @tranCount int ; set @tranCount = ( select @@tranCount ) ; print '执行【set xact_abort on】前 全局 @@tranCount = '+ cast( @tranCount as varchar(50) ) -- 执行【set xact_abort on】前 全局 @@tranCount = 1 set xact_abort on ; set @tranCount = ( select @@tranCount ) ; print '执行【set xact_abort on】后 全局 @@tranCount = '+ cast( @tranCount as varchar(50) ) -- 执行【set xact_abort on】后 全局 @@tranCount = 1 ------------------------------------------------------------------------------------------------------------------------------------------------------ begin tran tran02 ; set @tranCount = ( select @@tranCount ) ; print '执行【begin tran tran02】进入 子事务后 全局 @@tranCount = '+ cast( @tranCount as varchar(50) ) -- 执行【begin tran tran02】进入 子事务后 全局 @@tranCount = 2 ------------------------------------------------------------------------------------------------------------------------------------------------------ save tran tran_01 ; set @tranCount = ( select @@tranCount ) ; print '执行【save tran tran_01】 保存 事务点后 全局 @@tranCount = '+ cast( @tranCount as varchar(50) ) -- 执行【save tran tran_01】 保存 事务点后 全局 @@tranCount = 2 ------------------------------------------------------------------------------------------------------------------------------------------------------ -- 条件判断,回滚事务 IF EXISTS( SELECT TOP 1 * FROM dbo.test WHERE ID = @ID ) begin rollBack tran tran_01 ; set @tranCount = ( select @@tranCount ) ; print '执行【rollBack tran tran_01】回滚 保存点 事务后 全局 @@tranCount = '+ cast( @tranCount as varchar(50) ) -- commit tran tran02x ; set @tranCount = ( select @@tranCount ) ; print '执行【commit tran tran02】提交 子事务后 全局 @@tranCount = '+ cast( @tranCount as varchar(50) ) -- return 1 ; -- 1 已存在 ID end ------------------------------------------------------------------------------------------------------------------------------------------------------ -- 业务逻辑 开始 insert test ( ID, UserID, Name) VALUES ( @ID ,@UserID ,@Name) -- (1 行受影响) -- 业务逻辑 结束 begin tran tran03 ; save tran tran03 ; insert test ( ID, UserID, Name) VALUES ( @ID+100 ,@UserID ,@Name) -- (1 行受影响) commit tran tran02x ; rollBack tran tran03 ; ------------------------------------------------------------------------------------------------------------------------------------------------------ -- 执行过程中,发生错误 IF @@error <> 0 begin rollBack tran tran_01 ; set @tranCount = ( select @@tranCount ) ; print '执行【rollBack tran tran_01】回滚 保存点 事务后 全局 @@tranCount = '+ cast( @tranCount as varchar(50) ) -- commit tran tran02x ; set @tranCount = ( select @@tranCount ) ; print '执行【commit tran tran02】提交 子事务后 全局 @@tranCount = '+ cast( @tranCount as varchar(50) ) -- return 2 ; -- '执行过程中,发生错误 !' end ------------------------------------------------------------------------------------------------------------------------------------------------------ commit tran tran02x ; set @tranCount = ( select @@tranCount ) ; print '执行【commit tran tran02】 提交 子事务后 全局 @@tranCount = '+ cast( @tranCount as varchar(50) ) -- 执行【commit tran tran02】 提交 子事务后 全局 @@tranCount = 1 set xact_abort off; set @tranCount = ( select @@tranCount ) ; print '执行【set xact_abort off】后 全局 @@tranCount = '+ cast( @tranCount as varchar(50) ) -- 执行【set xact_abort off】后 全局 @@tranCount = 1 return 3 ; -- '执行完毕 !' end go --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- 调用父存储过程: select * from test declare @return_value int exec @return_value = aTran_1 @ID = 1 ,@UserID = 0 ,@Name = '0' print 'return Value = '+ cast( @return_value as varchar(50) ) select * from test /* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- 结果如下: (0 行受影响) 执行【begin tran】 进入 父事务前 全局 @@tranCount = 0 执行【begin tran】 进入 父事务后 全局 @@tranCount = 1 执行【set xact_abort on】前 全局 @@tranCount = 1 执行【set xact_abort on】后 全局 @@tranCount = 1 执行【begin tran tran02】进入 子事务后 全局 @@tranCount = 2 执行【save tran tran_01】 保存 事务点后 全局 @@tranCount = 2 (1 行受影响) 执行【commit tran tran02】 提交 子事务后 全局 @@tranCount = 1 执行【set xact_abort off】后 全局 @@tranCount = 1 消息 245,级别 16,状态 1,过程 aTran_2,行 58 [批起始行 114] 在将 varchar 值 '执行完毕 !' 转换成数据类型 int 时失败。 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 不会再报"execute 后的事务计数指示 begin 和 commit 语句的数目不匹配"之类的错误了, 实际上就是在每个嵌套的子过程中标明当前事务点, 每个子事务 只提交/回滚 子事务点, 而不是回滚整个事务! --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- SET xact_abort { ON | OFF } 注释 当 SET xact_abort 为 ON 时,如果 Transact-SQL 语句产生运行时错误,整个事务将终止并回滚。为 OFF 时,只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。编译错误(如语法错误)不受 SET xact_abort 的影响。 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
返回
保存