2012-08-18 119 views
4

我有以下代碼,並且我想知道,作爲一個通用示例,如果事務處於打開狀態(如果它以RETURN退出)。返回與TRY-CATCH塊交易內部

BEGIN TRANSACTION 
    BEGIN TRY 
     IF NOT EXISTS(SELECT 1 FROM dbo.tblProducts WHERE intProductID = @intProductID) 
      BEGIN 
       SELECT 'Product does not exists' AS strMessage 
       RETURN 
      END 

     UPDATE dbo.tblProducts SET 
      curPrice = 10 
     WHERE 
      intProductID = @intProductID 

     SELECT 'Success' AS strMessage 

    END TRY 

    BEGIN CATCH 
     SELECT ERROR_MESSAGE() AS strMessage 
     IF @@TRANCOUNT > 0 
      ROLLBACK TRANSACTION 
    END CATCH 

IF @@TRANCOUNT > 0 
    COMMIT TRANSACTION 
+0

我很肯定答案是肯定的,交易是開放的。事務不以存儲過程的上下文爲條件;他們是數據庫中的狀態。然而,文檔在這一點上非常明確,而且您正在談論數據庫的細微之處,所以我建議您閱讀SQL Server文檔。 –

+0

我只是拉存在和評估@@ rowcount http://msdn.microsoft.com/en-us/library/ms187316.aspx – Paparazzi

+0

或者如果你想知道什麼'UPDATE'上使用'OUTPUT'子句沒有進行'EXISTS'測試就改變了。 (關於Blam評論的變體)我的首選是讓每個退出路徑顯式提交或回滾。這表明我確實做出了決定。 – HABO

回答

0

該代碼可以使用嵌套事務:

BEGIN TRY 
    IF @@TRANCOUNT > 0 
     SAVE TRANSACTION MyTransactionName 
    ELSE 
     BEGIN TRANSACTION MyTransactionName 

    IF NOT EXISTS(SELECT 1 FROM dbo.tblProducts WHERE intProductID = @intProductID) 
     BEGIN 
      SELECT 'Product does not exists' AS strMessage 
      ROLLBACK TRANSACTION MyTransactionName 
      RETURN 
     END 

    UPDATE dbo.tblProducts SET 
     curPrice = 10 
    WHERE 
     intProductID = @intProductID 

    SELECT 'Success' AS strMessage 

    COMMIT TRANSACTION MyTransactionName 
END TRY 

BEGIN CATCH 
    SELECT ERROR_MESSAGE() AS strMessage 
    ROLLBACK TRANSACTION MyTransactionName 
END CATCH 
3

我只是通過運行上方,然後檢查SELECT @@TRANCOUNT,然後嘗試進行ROLLBACK代碼嘗試這樣做。退貨後,@@TRANCOUNT爲1,我能夠成功交易rollback,表明transaction保持打開狀態。

6

它應該像下面

BEGIN TRY 
    SET NOCOUNT ON 
    SET XACT_ABORT ON 
    BEGIN TRANSACTION 
     IF NOT EXISTS(SELECT 1 FROM dbo.tblProducts 
          WHERE intProductID = @intProductID) 
     BEGIN 
      SELECT 'Product does not exists' AS strMessage 
      Rollback TRan 
      RETURN 
     END 

     UPDATE dbo.tblProducts SET 
     curPrice = 10 
     WHERE 
     intProductID = @intProductID 

     SELECT 'Success' AS strMessage 
    COMMIT TRAN 
END TRY 

BEGIN CATCH 
    SELECT ERROR_MESSAGE() AS strMessage 
    ROLLBACK TRANSACTION 
END CATCH 
+1

可能值得一提的是,使用TRY,CATCH意味着您必須將'RAISERROR'視爲錯誤。如果OP在終端中只運行一次這種方法,那麼這種方法就沒有問題,但是如果它需要進入最佳狀態,人們纔會知道CATCH中的'RAISERROR',以避免它失敗。 – Adamantish