Vig*_*r A 81 sql sqlexception sql-server-2012
我有一个插入存储过程,它将数据提供给Table1并从Table1获取Column1值并调用第二个存储过程,它将为Table2提供数据.
但是,当我将第二个存储过程称为:
Exec USPStoredProcName
Run Code Online (Sandbox Code Playgroud)
它给我的错误如下:
EXECUTE之后的事务计数表示BEGIN和COMMIT语句的数量不匹配.先前的计数= 1,当前计数= 0.
我已经阅读了其他类似问题的答案,但我无法找到确切的提交计数在哪里搞砸了.
Rem*_*anu 98
如果您有一个TRY/CATCH块,那么可能的原因是您正在捕获事务中止异常并继续.在CATCH块中,您必须始终检查XACT_STATE()
并处理适当的中止和不可拒绝(注定)事务.如果你的调用者启动了一个事务并且calee命中了一个死锁(它中止了事务),那么被调用者如何与调用者通信该事务被中止并且它不应该继续"照常营业"?唯一可行的方法是重新引发异常,强制调用者处理这种情况.如果你静默地吞下一个中止的事务并且调用者继续假设仍然在原始事务中,那么只有混乱才能确保(并且你得到的错误就是引擎试图保护自己的方式).
我建议您查看异常处理和嵌套事务,这些事务显示可以与嵌套事务和异常一起使用的模式:
create procedure [usp_my_procedure_name]
as
begin
set nocount on;
declare @trancount int;
set @trancount = @@trancount;
begin try
if @trancount = 0
begin transaction
else
save transaction usp_my_procedure_name;
-- Do the actual work here
lbexit:
if @trancount = 0
commit;
end try
begin catch
declare @error int, @message varchar(4000), @xstate int;
select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
if @xstate = -1
rollback;
if @xstate = 1 and @trancount = 0
rollback
if @xstate = 1 and @trancount > 0
rollback transaction usp_my_procedure_name;
raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
end catch
end
go
Run Code Online (Sandbox Code Playgroud)
seg*_*uso 51
我也有这个问题.对我来说,原因是我在做
return
commit
Run Code Online (Sandbox Code Playgroud)
代替
commit
return
Run Code Online (Sandbox Code Playgroud)
在一个存储过程中.
Ama*_*ian 17
这通常发生在事务启动并且未提交或未回滚时.
如果您的存储过程中出现错误,这可能会锁定数据库表,因为在没有异常处理的情况下由于某些运行时错误而未完成事务您可以使用如下所述的异常处理. SET XACT_ABORT
SET XACT_ABORT ON
SET NoCount ON
Begin Try
BEGIN TRANSACTION
//Insert ,update queries
COMMIT
End Try
Begin Catch
ROLLBACK
End Catch
Run Code Online (Sandbox Code Playgroud)
就我而言,错误是RETURN
由BEGIN TRANSACTION
. 所以我有这样的事情:
Begin Transaction
If (@something = 'foo')
Begin
--- do some stuff
Return
End
commit
Run Code Online (Sandbox Code Playgroud)
它需要是:
Begin Transaction
If (@something = 'foo')
Begin
--- do some stuff
Rollback Transaction ----- THIS WAS MISSING
Return
End
commit
Run Code Online (Sandbox Code Playgroud)
如果您的存储过程在打开事务后遇到编译失败(例如找不到表、无效的列名),也会发生这种情况。
我发现我必须使用 2 个存储过程,一个是“worker”,一个是带有 try/catch 的包装器,两者的逻辑类似于 Remus Rusanu 概述的逻辑。worker catch 用于处理“正常”失败,wrapper catch 用于处理编译失败错误。
https://msdn.microsoft.com/en-us/library/ms175976.aspx
不受 TRY…CATCH 结构影响的错误
当以下类型的错误发生在与TRY…CATCH 构造相同的执行级别时,它们不会被 CATCH 块处理:
- 阻止批处理运行的编译错误,例如语法错误。
- 语句级重编译过程中出现的错误,例如由于名称解析延迟导致编译后出现对象名称解析错误。
希望这可以帮助其他人节省几个小时的调试时间......