use*_*358 5 sql-server t-sql transaction exception code
在 SQL Server 代码块中,放置提交事务的最佳位置是什么?在 try catch 块内部还是外部?
例如,选项 A 或选项 B 是正确的方法还是主观选择?
选项A
CREATE PROCEDURE DummyProc
BEGIN TRY
BEGIN TRANSACTION
INSERT sometable(a, b) VALUES (@a, @b)
INSERT sometable(a, b) VALUES (@b, @a)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF @@trancount > 0 ROLLBACK TRANSACTION
DECLARE @msg nvarchar(2048) = error_message()
RAISERROR (@msg, 16, 1)
RETURN 55555
END CATCH
Run Code Online (Sandbox Code Playgroud)
选项B
CREATE PROCEDURE DummyProc
BEGIN TRY
BEGIN TRANSACTION
INSERT sometable(a, b) VALUES (@a, @b)
INSERT sometable(a, b) VALUES (@b, @a)
END TRY
BEGIN CATCH
IF @@trancount > 0 ROLLBACK TRANSACTION
DECLARE @msg nvarchar(2048) = error_message()
RAISERROR (@msg, 16, 1)
RETURN 55555
END CATCH
IF @@trancount > 0 COMMIT TRANSACTION
Run Code Online (Sandbox Code Playgroud)
在选项B中,当在块外进行提交时是否有可能发生一些错误TRY-CATCH
?
我发现执行此操作的最佳方法是以下代码:
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRANSACTION
/*
Code goes here
*/
COMMIT TRANSACTION
END TRY
BEGIN CATCH
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
RAISERROR (@ErrorMessage, -- Message text.
@ErrorSeverity, -- Severity.
@ErrorState -- State.
);
-- If >= SQL 2012 replace all code in catch block above with
-- THROW;
WHILE @@TRANCOUNT > 0
BEGIN
ROLLBACK TRANSACTION;
END
END CATCH
Run Code Online (Sandbox Code Playgroud)
请注意,使用 XACT_ABORT 来确保有效捕获错误,BEGIN 和 COMMIT 语句都位于 TRY 块内,以及 @@Trancount 的 WHILE - 这应该确保回滚嵌套事务(并不总是适用)
对于 2012 以上的 SQL 版本,THROW 语句还可以替换 RAISERROR,以重新抛出捕获的异常/错误。
正如 Dan Guzman 在他的评论中指出的那样,XACT_ABORT 对于捕获 TRY/CATCH 构造不会捕获的错误非常有用,包括超时、运行时排序错误等
归档时间: |
|
查看次数: |
20530 次 |
最近记录: |