这是存储过程中的良好写入事务吗

问题描述

| 这是我第一次使用交易,我只是想知道我做对了吗。我应该改变一些东西吗? 我插入帖子(wisp)。当插入帖子时,我需要在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.\',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.\',1)
            RETURN
        END

COMMIT
使用基于@gbn答案的try / catch:
ALTER PROCEDURE [dbo].[sp_CreateWisp]
@m_UserId uniqueidentifier,@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,WispText)
        VALUES
        (@m_UserId,@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\',1)
END CATCH
GO
    

解决方法

        从SQL Server 2005开始,您将使用TRY / CATCH 回滚进入CATCH块,但否则代码看起来不错(使用SCOPE_IDENTITY()等)。我也会用
SET XACT_ABORT,NOCOUNT ON
这是我的模板:包含TRY CATCH ROLLBACK模式的嵌套存储过程? 编辑: 这允许根据DeveloperX的答案进行嵌套交易 根据Randy的评论,此模板还允许进行更高级别的交易     ,        我认为它一直都不好,但是如果您想同时使用多个存储过程,那将是不好的,因为每个存储过程都是独立处理事务的 但是在这种情况下,您应该使用try catch block进行异常处理,并防止在引发异常时保持事务打开     ,        我从来没有考虑过将事务放入存储过程中是一个好主意。我认为最好在更高级别启动事务,以便更好地协调多个数据库(例如存储过程)调用并将它们全部视为一个事务。