SQL Server 2008 R2事务是必需的@@ error并且需要ROLLBACK TRANS

时间:2014-01-22 17:50:06

标签: sql sql-server-2008 transactions sql-server-2008-r2

我的同事在程序中有这个:

BEGIN TRAN
 --Some deletes and inserts
IF(@@error <> 0)
BEGIN
  ROLLBACK TRAN
  RETURN
END
COMMIT TRAN

我在存储过程中有另一个只是:

BEGIN TRANSACTION
  --Some deltes and inserts
COMMIT TRANSACTION

我已经测试过并发现我的程序总是在错误期间(例如更改列数据类型等测试)回滚所有内容而不显式编码回滚。另外我已经读过,对于SQL Server 2005及更高版本,使用@@error条件已过时。

您认为为SQL Server 2008 R2及更高版本执行事务的正确方法是什么?感谢

3 个答案:

答案 0 :(得分:12)

ROLLBACK是必要的!

我会基于此模板为SQL Server 2005和更新版本执行存储过程:

BEGIN TRANSACTION
BEGIN TRY

    -- put your T-SQL commands here    

    -- if successful - COMMIT the work
    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    -- handle the error case (here by displaying the error)
    SELECT 
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_STATE() AS ErrorState,
        ERROR_PROCEDURE() AS ErrorProcedure,
        ERROR_LINE() AS ErrorLine,
        ERROR_MESSAGE() AS ErrorMessage

    -- in case of an error, ROLLBACK the transaction    
    ROLLBACK TRANSACTION

    -- if you want to log this error info into an error table - do it here 
    -- *AFTER* the ROLLBACK
END CATCH

答案 1 :(得分:4)

@@ ERROR变量存在问题。 这是一个全局变量,因此如果您正在执行以下操作:

BEGIN TRAN

   --inserts
   --deletes
   --updates
   -- last operation

IF(@@error <> 0)
BEGIN
  ROLLBACK TRAN
  RETURN
END
COMMIT TRAN

@@ error仅包含上一次操作的结果。因此,这段代码可以掩盖先前操作中的错误。

我的建议是,如果您可以在应用程序级别管理事务,请在应用程序级别执行。 在服务器端处理错误不适用于胆小的人,也不会改善你的应用程序的内部滥用。

答案 2 :(得分:0)

在数据库中创建以下过程,然后在catch块中创建,exec RethrowError。 关于这一点的好处是你不必从主存储过程

传递任何参数
CREATE PROCEDURE [dbo].[RethrowError] AS
-- Return if there is no error information to retrieve.
IF ERROR_NUMBER() IS NULL
    RETURN;

DECLARE 
    @ErrorMessage    NVARCHAR(4000),
    @ErrorNumber     INT,
    @ErrorSeverity   INT,
    @ErrorState      INT,
    @ErrorLine       INT,
    @ErrorProcedure  NVARCHAR(200);

-- Assign variables to error-handling functions that 
-- capture information for RAISERROR.
SELECT 
    @ErrorNumber = ERROR_NUMBER(),
    @ErrorSeverity = ERROR_SEVERITY(),
    @ErrorState = ERROR_STATE(),
    @ErrorLine = ERROR_LINE(),
    @ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-');

-- Building the message string that will contain original
-- error information.
SELECT @ErrorMessage = 
    N'Error %d, Level %d, State %d, %s, Line %d' + ERROR_MESSAGE();

-- Raise an error: msg_str parameter of RAISERROR will contain
-- the original error information.
RAISERROR 
    (
    @ErrorMessage, 
    @ErrorSeverity, 
    1,               
    @ErrorNumber,    -- parameter: original error number.
    @ErrorSeverity,  -- parameter: original error severity.
    @ErrorState,     -- parameter: original error state.
    @ErrorProcedure, -- parameter: original error procedure name.
    @ErrorLine       -- parameter: original error line number.
    );


GO

CREATE PROCEDURE YourProcedure

AS

BEGIN TRANSACTION

BEGIN TRY

--Put your code in here


END TRY


BEGIN CATCH

EXEC RethrowError

END CATCH


END