首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >错误时退出并回滚脚本中的所有内容

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

Stack Overflow用户
提问于 2010-05-26 08:05:08
回答 5查看 37K关注 0票数 8

我有一个TSQL脚本,它可以进行大量的数据库结构调整,但是在发生故障时让它通过并不安全。

要说清楚:

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

我得到的是按以下顺序排列的东西

代码语言:javascript
运行
复制
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

只是为了说明我的工作..。现在不能详细说明问题..。

当我引入一个错误(测试是否回滚)时,我得到一条语句,即ROLLBACK事务找不到相应的BEGIN事务。这让我相信,当真的出错的时候,交易已经被扼杀了。我还注意到,脚本没有在错误时完全退出,因此在错误发生后尝试执行所有语句。(当新表出现时,我注意到了这一点,当时我并没有想到它们,因为它应该回滚)

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-05-26 08:16:21

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

然而,执行将继续到下一批。所以,在执行错误后,批中的所有内容都在批中。然后,当稍后检查错误时,尝试回滚已经回滚的事务。

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

代码语言:javascript
运行
复制
raiserror('Error description here', 20, -1) with log

有关该问题的详细信息,请参见my answer here

因此,您需要在每一批之后检查@error,我认为这样的方法应该有效:

代码语言:javascript
运行
复制
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
票数 7
EN

Stack Overflow用户

发布于 2012-06-12 21:50:36

试着用回音。这将立即退出脚本或过程,并且不会执行以下任何语句。可以将此与BEGIN、ROLLBACK和COMMIT事务语句结合使用,以撤消任何数据损坏:

代码语言:javascript
运行
复制
    BEGIN
    BEGIN TRANSACTION

    <first batch>
    IF @@error <> 0
        begin
        RAISERROR ('first batch failed',16,-1)
        ROLLBACK TRANSACTION
        RETURN
        end

    <second batch>
    IF @@error <> 0
        begin
        RAISERROR ('second batch failed',16,-1)
        ROLLBACK TRANSACTION
        RETURN
        end

    PRINT 'WIN!'
    COMMIT TRANSACTION
    END
票数 4
EN

Stack Overflow用户

发布于 2011-10-25 12:33:32

我没有使用上升错误解决方案,因为它失败了,因为我没有管理权限。我用事务处理扩展了noexec on/off解决方案,如下所示:

代码语言:javascript
运行
复制
set noexec off

begin transaction
go

<First batch, do something here>
go
if @@error != 0 set noexec on;

<Second batch, do something here>
go
if @@error != 0 set noexec on;

<... etc>

declare @finished bit;
set @finished = 1;

SET noexec off;

IF @finished = 1
BEGIN
    PRINT 'Committing changes'
    COMMIT TRANSACTION
END
ELSE
BEGIN
    PRINT 'Errors occured. Rolling back changes'
    ROLLBACK TRANSACTION
END

显然,编译器“理解”IF中的@finished变量,即使出现错误并禁用了执行。但是,只有在未禁用执行时,该值才被设置为1。因此,我可以很好地提交或回滚事务。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2911103

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档