在我的历史过程中,我总是捕获异常,然后在
ROLLBACK
之后引发它。 我在 MSDN 中看到推荐的方法(对于 SQL2012+)是 THROW
。
基于此示例过程:
CREATE PROC my_procName
@id int
AS
BEGIN TRY
BEGIN TRAN
UPDATE [tbl_A] WHERE (ID=@id);
UPDATE [tbl_B] WHERE (fkID=@id);
UPDATE [tbl_C] WHERE (fkID=@id);
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRAN
DECLARE @ErrMsg nvarchar(4000)
DECLARE @ErrSeverity int
SET @ErrMsg = ERROR_MESSAGE()
SET @ErrSeverity = ERROR_SEVERITY()
RAISERROR(@ErrMsg, @ErrSeverity, 1)
END CATCH
GO
这是抛出异常同时保留
ROLLBACK
的正确方法吗?
CREATE PROC my_procName
@id int
AS
BEGIN TRY
BEGIN TRAN
UPDATE [tbl_A] WHERE (ID=@id);
UPDATE [tbl_B] WHERE (fkID=@id);
UPDATE [tbl_C] WHERE (fkID=@id);
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRAN
THROW
END CATCH
GO
我已经查看了 MSDN、Google 和此网站的示例,但没有一个包含
ROLLBACK
,所以这只是一个需要绝对确定的快速问题。
仅供记录,THROW 语句之前的语句应以分号终止。但通常您的方法是正确的 - THROW 结束批处理,因此必须是您要在 catch 块中执行的最后一条语句。您可以选择将 THROW 与参数一起使用:
THROW [ { error_number | @local_variable },
{ message | @local_variable },
{ state | @local_variable } ]
[ ; ]
不,你实际上根本不需要any
CATCH
。
SET XACT_ABORT ON;
,服务器将处理回滚。如果您需要的只是回滚和重新抛出,那么捕获是没有意义的。
CREATE PROC my_procName
@id int
AS
SET XACT_ABORT, NOCOUNT ON;
BEGIN TRAN;
UPDATE [tbl_A]
WHERE ID = @id;
UPDATE [tbl_B]
WHERE fkID = @id;
UPDATE [tbl_C]
WHERE fkID = @id;
COMMIT;