2011-06-06 76 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参数将错误信息返回给客户端程序。