IF @starttrancount = 0 BEGIN TRANSACTION
IF @starttrancount = 0 COMMIT TRANSACTION
使用这些是因为,@starttrancount 保证只让最外层的存储过程使用事务,因此只存在一个事务。
例子:我们要执行最外层程序,那么事务必须只在最外层程序中使用。
外部存储过程
CREATE PROCEDURE sp_outer
AS
SET XACT_ABORT, NOCOUNT ON
DECLARE @starttrancount int
BEGIN TRY
SELECT @starttrancount = @@TRANCOUNT -- Initially @@TRANSCOUNT =0
IF @starttrancount = 0
BEGIN TRANSACTION -- @@TRANSCOUNT =1
EXEC sp_inner -- Inner Procedure is called with @@TRANSCOUNT =1
-- so that Transaction in inner procedure will not be used.
-- Per Transaction is exists.
IF @starttrancount = 0
COMMIT TRANSACTION -- @@TRANSCOUNT = 0
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0 AND @starttrancount = 0
ROLLBACK TRANSACTION -- If Error occurs Rollback takes place.
RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
END CATCH
GO
2.内部存储过程
CREATE PROCEDURE sp_inner
AS
SET XACT_ABORT, NOCOUNT ON
DECLARE @starttrancount int
BEGIN TRY
SELECT @starttrancount = @@TRANCOUNT -- @@TRANCOUNT =1
IF @starttrancount = 0
BEGIN TRANSACTION -- Skipped
[...Perform work, call nested procedures...]
IF @starttrancount = 0
COMMIT TRANSACTION -- Skipped
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0 AND @starttrancount = 0
ROLLBACK TRANSACTION -- if Error Caught Roll back does not happen here
RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc] -- Error thrown to outer stored procedure.
END CATCH
GO
为什么 SELECT @starttrancount = @@TRANCOUNT ,而不是直接使用 @@TRANCOUNT ?
由于两个存储过程中都存在@@TRANSCOUNT 范围,因此使用@starttrancount 变量来维护过程范围内的值。