2015-05-11 126 views
0

我第一次使用事務,所以我可能會問一個愚蠢的問題。什麼是使用多個保存點的正確方法

我想在3個表中插入數據:

Table1(p1,p2,p3) 
Table2(q1,q2) 
Table3(t3,fk1,fk2) 

例如,如果出現錯誤和數據不能插入Table2,從Table1數據不會丟失,Table3保持不變(反之亦然) 。

到目前爲止我已經嘗試了兩個版本,但沒有一個令人滿意。

CREATE PROCEDURE InsertInto(@p1,@p2,@p3,@q1,@q2,@t3)) 
AS BEGIN 

BEGIN TRAN 
SET XACT_ABORT OFF 

SAVE TRANSACTION point1 
BEGIN TRY 
    DECLARE @fk1 INT 
    INSERT INTO Table1 VALUES (@p1,@p2,@p3) 
    SELECT @fk1 = Table1.Id FROM Table1 WHERE Table1.p1 = @p1 

    SAVE TRANSACTION point2 
    BEGIN TRY 
     DECLARE @fk2 INT 
     INSERT INTO Table2 VALUES (@q1,@q2) 
     SELECT @fk2 = Table2.Id FROM Table2 WHERE Table2.q1 = @q1 

     SAVE TRANSACTION point3 
     BEGIN TRY 
      INSERT INTO Table3 VALUES (@t3, @fk1, @fk2) 
      COMMIT TRAN 
      END TRY 
     BEGIN CATCH 
      ROLLBACK TRANSACTION point3 
      COMMIT TRAN 
     END CATCH 

    END TRY 
    BEGIN CATCH 
     ROLLBACK TRANSACTION point2 
     COMMIT TRAN 
    END CATCH 

END TRY 
BEGIN CATCH 
    ROLLBACK TRANSACTION point1 
    COMMIT TRAN 
END CATCH 
END 

但如果數據不能在Table1插入,然後Table2可能的數據丟失,我不想失去任何東西:

第1版。所以,我試圖分裂它。

版本2:

CREATE PROCEDURE InsertInto(@p1,@p2,@p3,@q1,@q2,@t3) 
AS 
BEGIN 

BEGIN TRAN 
SET XACT_ABORT OFF 

SAVE TRANSACTION point1 
BEGIN TRY 
    DECLARE @fk1 INT 
    INSERT INTO Table1 VALUES (@p1,@p2,@p3) 
    SELECT @fk1 = Table1.Id FROM Table1 WHERE Table1.p1 = @p1 
END TRY 
BEGIN CATCH 
    ROLLBACK TRANSACTION point1 
    COMMIT TRAN 
END CATCH 

SAVE TRANSACTION point2 
BEGIN TRY 
    DECLARE @fk2 INT 
    INSERT INTO Table2 VALUES (@q1,@q2) 
    SELECT @fk2 = Table2.Id FROM Table2 WHERE Table2.q1 = @q1 
END TRY 
BEGIN CATCH 
    ROLLBACK TRANSACTION point2 
    COMMIT TRAN 
END CATCH 

SAVE TRANSACTION point3 
BEGIN TRY 
    INSERT INTO Table3 VALUES (@t3,@fk1,@fk2) 
    COMMIT TRAN 
END TRY 
BEGIN CATCH 
    ROLLBACK TRANSACTION point3 
    COMMIT TRAN 
END CATCH 
END 

但如果插入到表2失敗,我得到這個:

(1行(S)的影響)

(0行(S)的影響)
消息628,級別16,狀態0,過程插入進來,行26(第二個開始捕獲)
當沒有活動交易時,不能發出存儲交易上。

我該如何做到這一點?

+0

看來你不應該在這裏使用保存點,而只是在每一步之後提交,然後開始一個新的事務。你能澄清你爲什麼使用保存點嗎?也許你的代碼的某些用法根本不清楚。 – hvd

+0

我想了解如何使用保存點,以便在事務處理期間不丟失數據。 – user1012732

回答

1

SAVE TRAN要求事務計數> 0,因此您必須在前一個CATCH塊中提交事務。您有幾種選擇:

1)以下的(你可以使用相同的保存點的名稱,但回滾只會回滾到最後保存點)更換您的SAVE TRAN語句:

IF @@TRANCOUNT = 0 
    BEGIN TRAN; 
ELSE 
    SAVE TRAN tran1; 

2) CATCH塊,該COMMIT TRAN

BEGIN CATCH 
    ROLLBACK TRANSACTION point1 
    COMMIT TRAN 
    BEGIN TRAN 
END CATCH 

3後添加BEGIN TRAN)刪除所有的COMMIT TRAN的CATCH塊內部,並做在端部的單個COMMIT。

相關問題