2011-06-12 71 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

相关问题