我有一个长期运行的脚本,我希望将其包含在最多可能包含 100+个交易的交易中。
我想实现一些错误处理和重用代码。我在考虑使用标签和GOTO语句。
BEGIN TRY
BEGIN TRANSACTION abc
--DO SOMETHING
COMMIT TRANSACTION abc;
END TRY
BEGIN CATCH
GOTO ERROR_OUT
END CATCH
ERROR_OUT:
SELECT ERROR_MESSAGE() [ErrorMessage];
ROLLBACK;
使用多笔交易时应该做些什么?
在我强制出错的简单测试中,我注意到ERROR_MESSGE()SELECT语句没有返回结果。
使用标签时,有没有办法让select语句返回结果?
答案 0 :(得分:4)
Declare @Table table (Num float,Den float,Pct float)
Insert into @Table values (25,100,0),(50,0,0)
BEGIN TRY
BEGIN TRANSACTION abc
-- Force a Divide by Zero on 2nd record
Update @Table Set Pct=Num/Den
COMMIT TRANSACTION abc;
Select * from @Table
GOTO CLEAN_OUT
END TRY
BEGIN CATCH
Declare @Error varchar(max)=Error_Message()
GOTO ERROR_OUT
END CATCH
ERROR_OUT:
ROLLBACK;
Select ErrorMessage=@Error
Select * From @Table
CLEAN_OUT:
Go
返回
ErrorMessage
Divide by zero error encountered.
Num Den Pct
25 100 0
50 0 0
然后用(50,125,0)
尝试答案 1 :(得分:3)
评论太长了。
一般情况下,不鼓励程序员使用goto
。原因是它是一个控制流原语,并且存在许多常用案例的替代方案:if
/ then / else
,while
,等等。
但是,在某些情况下goto
非常有用。错误处理就是其中之一。如果你谷歌“转到错误处理”,不难找到this或this等解释(虽然对于C,我认为推理非常相似)。
我经常在SQL Server存储过程中使用goto
来实现此目的。虽然在我的情况下,目标是在离开存储过程时实现适当的审计和错误处理。
您的用例似乎是一个很好的例子,goto
是一种非常合理的代码块编码方式。我发现“数百个交易”部分更值得怀疑。就个人而言,我喜欢明确处理交易的时间和地点,因此我更有可能写下:
. . .
begin catch:
rollback ;
goto error_out;
end;
也就是说,要显式回滚事务开始的“旁边”事务,而不是在某个远程代码块中执行该操作。