【问题标题】:tsql mutiple inserts in a transaction with rollbacksql在具有回滚的事务中多次插入
【发布时间】:2014-01-13 12:03:05
【问题描述】:

我有一个存储过程,当执行它时,它会在 2 个表中插入几条记录。

假设在作者表中插入一条记录并在书籍表中插入几条记录(作者的书籍)。

如何在回滚事务中进行所有插入?

我读了一些文章/博客,@@trancount/@@error/XACT_STATE() 让我很困惑。

最好的方法是什么?

这是我的过程:

CREATE PROCEDURE [dbo].[proc_addAuthors]
    @bookid1 int,   @bookid2 int,   @bookid3 int,   @bookid4 int,   @bookid5 int,
    @authInfo 
AS
    insert into author...(leave out params)
    --get authorId
    ...

    --insert books (leave out validation checks...)
    insert into author2book(authorId, bookId) values(@authorid, @bookid1)
    ...

RETURN 0

【问题讨论】:

  • 你的sql server是什么版本的?
  • @rudibruchez 它在问题的标签中 - 2008。

标签: sql-server sql-server-2008 tsql


【解决方案1】:

如果您只想确保插入都成功完成,或者在发生错误时都回滚,则需要将以下内容添加到存储过程中:

CREATE PROCEDURE [dbo].[proc_addAuthors]
    @bookid1 int,   @bookid2 int,   @bookid3 int,   @bookid4 int,   @bookid5 int,
    @authInfo 
AS

SET XACT_ABORT ON;  -- Automatically rollback if an error occurs.
BEGIN TRANSACTION;  

    insert into author...(leave out params)
    --get authorId
    ...

    --insert books (leave out validation checks...)
    insert into author2book(authorId, bookId) values(@authorid, @bookid1)
    ...

COMMIT TRANSACTION;

RETURN 0

【讨论】:

    【解决方案2】:
    CREATE PROCEDURE addTitle(@title_id VARCHAR(6), @au_id VARCHAR(11),
                              @title VARCHAR(20), @title_type CHAR(12))
    AS
    
    BEGIN TRAN
        INSERT titles(title_id, title, type)
        VALUES (@title_id, @title, @title_type)
    
        IF (@@ERROR <> 0) GOTO ERR_HANDLER
    
        INSERT titleauthor(au_id, title_id)
        VALUES (@au_id, @title_id)
    
        IF (@@ERROR <> 0) GOTO ERR_HANDLER
    
    COMMIT TRAN
    
    RETURN 0
    
    ERR_HANDLER:
    PRINT 'Unexpected error occurred!'
    ROLLBACK TRAN
    RETURN 1
    

    【讨论】:

      【解决方案3】:

      这是使用现代 TRY CATCH 块测试错误的方法

      CREATE PROCEDURE [dbo].[proc_addAuthors]
          @bookid1 int,   @bookid2 int,   @bookid3 int,   @bookid4 int,   @bookid5 int,
          @authInfo 
      AS
          BEGIN TRY
              BEGIN TRANSACTION
              insert into author...(leave out params)
              --get authorId
              ...
      
              --insert books (leave out validation checks...)
              insert into author2book(authorId, bookId) values(@authorid, @bookid1)
              ...
              COMMIT TRANSACTION
          END TRY
          BEGIN CATCH
              SELECT ERROR_MESSAGE() as errorMessage -- for example
              ROLLBACK
              RETURN 1 -- for example
          END CATCH
      
          RETURN 0
      

      【讨论】:

        【解决方案4】:

        使用 Try..Catch 块可以让您访问错误函数,您可以使用它来获取有关错误的详细信息。

        CREATE PROCEDURE [dbo].[proc_addAuthors]
        @bookid1 int,   @bookid2 int,   @bookid3 int,   @bookid4 int,   @bookid5 int,
        @authInfo 
        AS
        BEGIN
         SET NOCOUNT ON;
        
          DECLARE @NewAuthorID INT;
        
        
          BEGIN TRY
        
            BEGIN TRANSACTION
                insert into author...(leave out params)
                --get authorId
                SET @NewAuthorID = SCOPE_IDENTITY();  --<-- Get new AuthorID generated by Identity column
        
                --insert books (leave out validation checks...)
                insert into author2book(authorId, bookId)      --<-- use that NewAuthorID param here            
                        values(@NewAuthorID, @bookid1)
                ...
            COMMIT TRANSACTION
            RETURN 0
          END TRY
        
          BEGIN CATCH 
              IF (@@TRANCOUNT > 0)
                  ROLLBACK TRANSACTION
        
              DECLARE @ErrorNum int  
              SELECT @ErrorNum =  ERROR_NUMBER()
              SELECT ERROR_MESSAGE() AS ErrorMessage,
                     ERROR_LINE()    AS ErrorLine, 
                     --<--.... ( Other Error Functions )
        
              RETURN @ErrorNum
          END CATCH 
        END
        

        【讨论】:

        • @Scott 抱歉,您收到了什么错误消息??? n 是的,我错过了 ErrorNum 变量的数据类型,但您已经了解如何处理这种情况。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-07
        • 1970-01-01
        • 2016-06-23
        • 1970-01-01
        • 1970-01-01
        • 2016-05-11
        相关资源
        最近更新 更多