sql在具有回滚的事务中多次插入

Posted

技术标签:

【中文标题】sql在具有回滚的事务中多次插入【英文标题】:tsql mutiple inserts in a transaction with rollback 【发布时间】: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。 【参考方案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 变量的数据类型,但您已经了解如何处理这种情况。

以上是关于sql在具有回滚的事务中多次插入的主要内容,如果未能解决你的问题,请参考以下文章

即使有事务回滚,SQL 标识(自动编号)也会增加

关于MySQL回滚机制

即使使用事务回滚,SQL标识(自动编号)也会增加

ROLLBACK语句只能针对未提交的事务进行回滚操作,已提交的事务是不能回滚的?

如何创建表的回滚副本以防我插入或更新错误

在 Node.js 中处理回滚的 MySQL 事务