2011-06-12 115 views
4

這是我第一次使用交易,我只是想知道我是否正確。我應該改變什麼嗎? 我插入帖子(一縷)。當插入帖子時,我需要在commentableEntity表中生成ID並在wisp表中插入該ID。這是存儲過程中的良好寫入交易

ALTER PROCEDURE [dbo].[sp_CreateWisp] 
@m_UserId uniqueidentifier, 
@m_WispTypeId int, 
@m_CreatedOnDate datetime, 
@m_PrivacyTypeId int, 
@m_WispText nvarchar(200) 
AS 
BEGIN TRANSACTION 

    DECLARE @wispId int 

    INSERT INTO dbo.tbl_Wisps 
    (UserId,WispTypeId,CreatedOnDate,PrivacyTypeId,WispText) 
    VALUES 
    (@m_UserId,@m_WispTypeId,@m_CreatedOnDate,@m_PrivacyTypeId,@m_WispText) 

    if @@ERROR <> 0 
     BEGIN 
      ROLLBACK    
      RAISERROR ('Error in adding new wisp.', 16, 1) 
      RETURN 
     END 

    SELECT @wispId = SCOPE_IDENTITY() 

    INSERT INTO dbo.tbl_CommentableEntity 
    (ItemId) 
    VALUES 
    (@wispId) 

    if @@ERROR <> 0 
     BEGIN 
      ROLLBACK    
      RAISERROR ('Error in adding commentable entity.', 16, 1) 
      RETURN 
     END 

    DECLARE @ceid int 

    select @ceid = SCOPE_IDENTITY() 

    UPDATE dbo.tbl_Wisps SET CommentableEntityId = @ceid WHERE WispId = @wispId 

    if @@ERROR <> 0 
     BEGIN 
      ROLLBACK    
      RAISERROR ('Error in adding wisp commentable entity id.', 16, 1) 
      RETURN 
     END 

COMMIT 

使用基於@gbn答案try/catch語句:

ALTER PROCEDURE [dbo].[sp_CreateWisp] 
@m_UserId uniqueidentifier, 
@m_WispTypeId int, 
@m_CreatedOnDate datetime, 
@m_PrivacyTypeId int, 
@m_WispText nvarchar(200) 
AS 

SET XACT_ABORT, NOCOUNT ON 

DECLARE @starttrancount int 

BEGIN TRY 
    SELECT @starttrancount = @@TRANCOUNT 

    IF @starttrancount = 0 
     BEGIN TRANSACTION 

     DECLARE @wispId int 

     INSERT INTO dbo.tbl_Wisps 
     (UserId,WispTypeId,CreatedOnDate,PrivacyTypeId,WispText) 
     VALUES 
     (@m_UserId,@m_WispTypeId,@m_CreatedOnDate,@m_PrivacyTypeId,@m_WispText) 

     SELECT @wispId = SCOPE_IDENTITY() 

     INSERT INTO dbo.tbl_CommentableEntity 
     (ItemId) 
     VALUES 
     (@wispId) 

     DECLARE @ceid int 

     select @ceid = SCOPE_IDENTITY() 

     UPDATE dbo.tbl_Wisps SET CommentableEntityId = @ceid WHERE WispId = @wispId 

    IF @starttrancount = 0 
     COMMIT TRANSACTION 
END TRY 
BEGIN CATCH 
    IF XACT_STATE() <> 0 AND @starttrancount = 0 
     ROLLBACK TRANSACTION 
    RAISERROR ('Error in adding new wisp', 16, 1) 
END CATCH 
GO 

回答

6

你會使用try/catch語句,因爲SQL服務器2005+

你回滾進入CATCH塊,但你的代碼否則看起來不錯(使用SCOPE_IDENTITY()等)。我還用SET XACT_ABORT, NOCOUNT ON

這是我的模板:Nested stored procedures containing TRY CATCH ROLLBACK pattern?

編輯:

  • 這允許嵌套事務按照開發人員X的答案
  • 此模板還允許更高級別的交易按蘭迪的評論
+1

嗨,我根據您的模板添加了新的代碼。請確認它是好的,所以我可以關閉這個問題;) – 1110 2011-06-12 11:19:31

+0

@ 1110:是的,看起來不錯。 – gbn 2011-06-12 13:53:04

1

我認爲它一直不好,但如果你想使用更多的臨N一個存儲過程,同時它的不好是導致每個存儲過程處理獨立

但在這種情況下,你應該使用try catch塊,異常處理,並防止保持交易開放時的異常升高

交易
+0

請在我的答案中看到鏈接:易於嵌套 – gbn 2011-06-12 11:07:08

+0

是的,我的答案是關於將事務存儲在存儲過程中,在這種情況下,您的答案是正確的 – DeveloperX 2011-06-12 11:14:59

1

我從來沒有考慮過將事務存儲在存儲過程中。我認爲在更高級別開始交易要好得多,以便更好地協調多個數據庫(例如存儲過程)調用,並將它們全部視爲單個事務處理。

+0

然後您需要MSDTC參與。每個數據庫都不應該在可能的情況下調用原子嗎?無論如何,請參閱我的回答,以獲取處理該問題的模板。 – gbn 2011-06-12 11:08:22