2011-06-06 75 views
16

我從來沒有使用事務,提交和回滾之前,現在我需要使用一個。我已經在網上查了一些例子,以確保我確實正確地使用了這個,但是我仍然不確定我是否已經編寫了正確的代碼。我希望有人可以回顧並告訴我這是否正確。存儲過程事務

基本上我有2個應用程序的數據庫。一個是檔案 - 意味着不再被用戶操縱的數據將被移到這個數據庫中。但是,如果他們需要它,我會將所需的數據移回主數據庫以供使用。我的存儲過程低於:

CREATE PROCEDURE [dbo].[spReopenClosed] 
(
    @Return_Message VARCHAR(1024) = '' OUT,   
    @IID  uniqueidentifier, 
    @OpenDate smalldatetime, 
    @ReopenedBy uniqueidentifier 
) 
AS 
BEGIN 
    SET NOCOUNT ON; 

/****************************** 
* Variable Declarations 
*******************************/ 
    DECLARE  @ErrorCode int 



/****************************** 
* Initialize Variables 
*******************************/ 

    SELECT @ErrorCode = @@ERROR 

    IF @ErrorCode = 0 

    BEGIN TRANSACTION 
     /**************************************************************************** 
     * Step 1 
     * Copy the Closed from the Archive 
     ****************************************************************************/ 
     INSERT INTO OPS.dbo.SM_T_In 
     SELECT   
     FROM OPS_ARCHIVE.Archive.SM_T_In W 
     WHERE W.GUID = @IID 
      AND W.OpenDate = @OpenDate 


     IF @ErrorCode <> 0 
      BEGIN 
       -- Rollback the Transaction 
       ROLLBACK 

       RAISERROR ('Error in Copying from the archive', 16, 1) 
       RETURN 
      END 


     /**************************************************************************** 
     * Step 2 
     * copy the notes 
     ****************************************************************************/ 
     INSERT INTO OPS.dbo.SM_T_Notes 
     SELECT 
     FROM OPS_ARCHIVE.Archive.SM_T_Notes W 
     WHERE W.GUID = @IID 

     IF @ErrorCode <> 0 
      BEGIN 
       -- Rollback the Transaction 
       ROLLBACK 

       RAISERROR ('Error in copying the notes', 16, 1) 
       RETURN 
      END 

     /**************************************************************************** 
     * Step 3 
     * Delete the from the Archive - this will also delete the notes 
     ****************************************************************************/ 
     DELETE 
     FROM OPS_ARCHIVE.Archive.SM_T_In 
     WHERE OPS_ARCHIVE.Archive.SM_T_In.GUID = @IID 

     IF @ErrorCode <> 0 
      BEGIN 
       -- Rollback the Transaction 
       ROLLBACK 

       RAISERROR ('Error in deleting the items from the Archive', 16, 1) 
       RETURN 
      END 

     COMMIT 

     BEGIN 
      SELECT @ErrorCode = @@ERROR 

      IF @ErrorCode = 0 
        SELECT @Return_Message = 'All data was moved over' 
     END 



/************************************* 
* Get the Error Message for @@Error 
*************************************/ 
    IF @ErrorCode <> 0 
    BEGIN 
     SELECT @Return_Message = [Description]  -- Return the SQL Server error 
      FROM master.dbo.SYSMESSAGES 
     WHERE error = @ErrorCode 
    END 

/************************************* 
* Return from the Stored Procedure 
*************************************/ 
    RETURN @ErrorCode        -- =0 if success, <>0 if failure 
END 

我有兩個刀片,從2代表從歸檔數據庫的數據移動。如果這些插入成功,那麼我將從存檔數據庫中刪除數據。我會很感激任何反饋,我需要確保我正確地做到這一點。

感謝

+0

哪個版本的SQL Server?它在方法上有很大的不同。 – HLGEM 2011-06-06 14:01:55

+0

SQL Server 2005 – Taryn 2011-06-06 14:39:27

回答

28

哦我的rewrite迅速將這一概念TRY CATCH和交易你的SP按照您的要求,但我沒有檢查它。

此代碼將在SQL工作2005/2008

讓我知道如果這個反饋可以爲你

CREATE PROCEDURE [dbo].[spReopenClosed] 
(
    @Return_Message VARCHAR(1024) = '' OUT,   
    @IID  uniqueidentifier, 
    @OpenDate smalldatetime, 
    @ReopenedBy uniqueidentifier 
) 
AS 

    SET NOCOUNT ON; 

/****************************** 
* Variable Declarations 
*******************************/ 
    DECLARE  @ErrorCode int 
    DECLARE  @ErrorStep varchar(200) 

/****************************** 
* Initialize Variables 
*******************************/ 

    SELECT @ErrorCode = @@ERROR 

BEGIN TRY 

    BEGIN TRAN 
     /**************************************************************************** 
     * Step 1 
     * Copy the Closed from the Archive 
     ****************************************************************************/ 

     SELECT @ErrorStep = 'Error in Copying from the archive'; 

     INSERT INTO OPS.dbo.SM_T_In 
     SELECT *   
     FROM OPS_ARCHIVE.Archive.SM_T_In 
     WHERE GUID = @IID 
      AND W.OpenDate = @OpenDate 


     /**************************************************************************** 
     * Step 2 
     * copy the notes 
     ****************************************************************************/ 

     SELECT @ErrorStep = 'Error in copying the notes' 

     INSERT INTO OPS.dbo.SM_T_Notes 
     SELECT * 
     FROM OPS_ARCHIVE.Archive.SM_T_Notes 
     WHERE GUID = @IID 

     /**************************************************************************** 
     * Step 3 
     * Delete the from the Archive - this will also delete the notes 
     ****************************************************************************/ 

     SELECT @ErrorStep = 'Error in deleting the items from the Archive' 

     DELETE 
     FROM OPS_ARCHIVE.Archive.SM_T_In 
     WHERE OPS_ARCHIVE.Archive.SM_T_In.GUID = @IID 

    COMMIT TRAN 

    SELECT @ErrorCode = 0, @Return_Message = 'All data was moved over' 

    /************************************* 
    * Return from the Stored Procedure 
    *************************************/ 
    RETURN @ErrorCode        -- =0 if success, <>0 if failure 

END TRY 

BEGIN CATCH 
    /************************************* 
    * Get the Error Message for @@Error 
    *************************************/ 
    IF @@TRANCOUNT > 0 ROLLBACK 

    SELECT @ErrorCode = ERROR_NUMBER() 
     , @Return_Message = @ErrorStep + ' ' 
     + cast(ERROR_NUMBER() as varchar(20)) + ' line: ' 
     + cast(ERROR_LINE() as varchar(20)) + ' ' 
     + ERROR_MESSAGE() + ' > ' 
     + ERROR_PROCEDURE() 

    /************************************* 
    * Return from the Stored Procedure 
    *************************************/ 
    RETURN @ErrorCode        -- =0 if success, <>0 if failure 

END CATCH 
+1

很好的例子!謝謝 – Rich 2017-07-17 13:40:19

3

首先,數據庫是相當可靠的是有用的。如果它們失敗了,那麼比處理單個交易有更大的問題。所以我的反饋意見是你對一個簡單的事務有太多的錯誤檢查。失敗的插入是這樣一個不尋常的事件,您通常不會編寫代碼來處理它。

其次,這段代碼實際上不會「趕」的錯誤:

IF @ErrorCode <> 0 

在SQL語句中的錯誤將中止存儲過程,並返回給客戶端。您必須try ... catch才能真正處理存儲過程中的錯誤。第三,我儘量避免raiserr。它可以在服務器和客戶端都做出意想不到的事情。相反,請考慮使用output參數將錯誤信息返回給客戶端程序。

相關問題