在多个插入或更新周围使用事务的正确方法

Joe*_*ips 10 sql-server transactions

测试插入/更新失败并回滚此事务的正确方法是什么?我不认为我的工作会有效,因为我的插入/更新是3个单独的语句,而@@ ROWCOUNT只会反映最后执行的语句.

BEGIN TRANSACTION Script;
GO

INSERT INTO TableA (id) VALUES (1)
INSERT INTO TableB (id) VALUES (1)
UPDATE TableC SET id=1 WHERE id=2
GO

IF (@@ROWCOUNT=3 AND @@ERROR=0)
    BEGIN
    COMMIT
    END
ELSE
    BEGIN
    PRINT 'Error: Rolling back transaction'
    ROLLBACK TRANSACTION Script
    END
GO
Run Code Online (Sandbox Code Playgroud)

Nik*_*vić 42

如果在启动事务之前将SET XACT_ABORT设置为ON,则在发生错误时,将自动发回回滚.

SET XACT_ABORT ON

begin transaction

INSERT INTO TableA (id) VALUES (1)
INSERT INTO TableB (id) VALUES (1)
UPDATE TableC SET id=1 WHERE id=2

commit transaction
Run Code Online (Sandbox Code Playgroud)

如果你想自己做回滚,请使用try .. catch block.

begin transaction

begin try

  INSERT INTO TableA (id) VALUES (1)
  INSERT INTO TableB (id) VALUES (1)
  UPDATE TableC SET id=1 WHERE id=2

  commit transaction

end try

begin catch
  raiserror('Message here', 16, 1)
  rollback transaction
end catch
Run Code Online (Sandbox Code Playgroud)

  • 当事务回滚时,SET XACT_ABORT ON 属性会引发错误消息吗? (2认同)
  • @Raza是的.Xact_abort将自动中断执行流程和回滚.错误仍将传递给客户端. (2认同)

Ben*_*hul 5

我不知道您使用的是哪个版本,但自 SQL 2005 以来一直有 try/catch:

begin transaction
begin try
   INSERT INTO TableA (id) VALUES (1)
   INSERT INTO TableB (id) VALUES (1)
   UPDATE TableC SET id=1 WHERE id=2
end try
begin catch
   SELECT
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_STATE() AS ErrorState,
        ERROR_PROCEDURE() AS ErrorProcedure,
        ERROR_LINE() AS ErrorLine,
        ERROR_MESSAGE() AS ErrorMessage;
   while(@@trancount > 0)
   begin
      rollback transaction
   end
end catch
if (@@trancount <> 0)
begin
   commit transaction;
end
Run Code Online (Sandbox Code Playgroud)