GSe*_*erg 7 sql-server-2008 stored-procedures t-sql error-handling
在我永无止境地寻求通过保存交易射击自己的过程中,我似乎找到了更多实现任务目的的方法。这次的save transaction子句本身是没问题的,不过正因为如此,我才写了下面的代码。
考虑以下带有嵌套错误处理程序的完整示例:
begin try
begin try
select 'Step 1';
end try
begin catch
select 'Step 1 handler - handling ''' + error_message() + '''';
goto commit_and_exit;
end catch;
begin try
select 'Step 2';
raiserror('Step 2 error', 16, 1);
end try
begin catch
select 'Step 2 handler - handling ''' + error_message() + '''';
goto commit_and_exit;
end catch;
end try
begin catch
select 'Outer handler - handling ''' + error_message() + '''';
goto commit_and_exit;
end catch
commit_and_exit:
raiserror('Error raised for the caller to see', 16, 1);
Run Code Online (Sandbox Code Playgroud)
据记载是
GOTO
语句可用于跳转到同一个TRY
或CATCH
块内的标签或离开一个TRY
或CATCH
块。
或者可以吗?
鉴于上面的代码,一个理智的程序员会认为输出将是
第 1
步第 2
步第 2步处理程序 - 处理“第 2 步错误”
<引发的错误供调用者查看>
事实上,正在发生的事情是:
第 1
步第 2
步第 2步处理程序 - 处理“第 2 步错误”
外部处理程序 - 处理“引发的错误供调用者查看”
<引发的错误供调用者查看>
一步一步调试的时候,可以看到控制完全离开了try/catch块,然后报错,控制返回到最外面的catch
块,那个块执行,控制commit_and_exit:
再次执行,最后一个块被执行再次。
如果您有一些commit tran
s 或rollback trans
s commit_and_exit:
,您将尝试提交 tran 两次。考虑到可能存在由调用者启动的外部事务这一事实,结果可想而知。
我还尝试在外部块end_of_outer:
之前创建另一个标签 ,end try
以便控件try
“正常”离开外部块。有趣的是,这没有任何区别。
这到底是怎么回事,正确的做法是什么?
归档时间: |
|
查看次数: |
1096 次 |
最近记录: |