出错时退出并回滚脚本中的所有内容

Jan*_* W. 8 t-sql sql-server transactions sql-server-2005

我有一个TSQL脚本,可以进行大量的数据库结构调整,但是当它出现故障时让它通过是不安全的.

说清楚:

  • 使用MS SQL 2005
  • 它不是存储过程,只是一个脚本文件(.sql)

我所拥有的是以下顺序的东西

BEGIN TRANSACTION
    ALTER Stuff
    GO

    CREATE New Stuff
    GO

    DROP Old Stuff
    GO
IF @@ERROR != 0
    BEGIN
  PRINT 'Errors Found ... Rolling back'
  ROLLBACK TRANSACTION
  RETURN
    END
ELSE
     PRINT 'No Errors ... Committing changes'
     COMMIT TRANSACTION
Run Code Online (Sandbox Code Playgroud)

只是为了说明我正在使用的...现在不能详细说明,问题......

当我引入一个错误(测试事情是否被回滚)时,我得到一个声明,即ROLLBACK TRANSACTION找不到相应的BEGIN TRANSACTION.这让我相信当真正错误并且交易已经被杀死时.我还注意到,脚本没有完全退出错误,因此DID尝试在发生错误后执行每个语句.(我注意到这一点,当我没有期待它们时出现新表,因为它应该有回滚)

Blo*_*ard 7

发生错误时,将自动回滚事务,并中止当前批处理.

然而,执行继续进入下一批.因此,错误执行后批处理中的所有内容.然后,当您稍后检查错误时,您尝试回滚已经回滚的事务.

此外,要停止整个脚本,而不仅仅是当前批处理,您应该使用:

raiserror('Error description here', 20, -1) with log
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅我的答案.

所以你需要@error在每批之后检查一下,我认为这样的事情应该有效:

BEGIN TRANSACTION
GO

ALTER Stuff
GO

if @@error != 0 raiserror('Script failed', 20, -1) with log
GO

CREATE New Stuff
GO

if @@error != 0 raiserror('Script failed', 20, -1) with log
GO

DROP Old Stuff
GO

if @@error != 0 raiserror('Script failed', 20, -1) with log
GO

PRINT 'No Errors ... Committing changes'
COMMIT TRANSACTION
Run Code Online (Sandbox Code Playgroud)

  • 这基本上是我使用的,但形式如下: if @@error <> 0 or @@trancount = 0 begin if @@trancount > 0 rollback transaction set noexec on end (2认同)
  • 仅当 _stuff_ 是单个语句时才有效。`@@ERROR` 仅返回最后执行的语句的结果,因此如果 _stuff_ 由多个语句组成,则只有最后一个语句的错误才会导致执行此类错误处理。“尝试...捕捉”更好。 (2认同)