Exit and rollback everything in script on error

后端 未结 5 1677
我寻月下人不归
我寻月下人不归 2021-02-15 15:43

I have a TSQL script that does a lot of database structure adjustments but it\'s not really safe to just let it go through when something fails.

to make things clear:

相关标签:
5条回答
  • You could try something like this... If you are using Try block... The error level 16, (or most of application error), immediately transfers the control to the CATCH block without executing any further statements in the try block...

        Begin Transaction
    
    Begin Try
    
                        --  Do your Stuff
    
            If (@@RowCount <> 1) -- Error condition
            Begin
                Raiserror('Error Message',16,1)
            End
    
    
        Commit
    End Try
    Begin Catch
        IF @@Trancount > 0
        begin
            Rollback Transaction
        End
    
        Declare @ErrMsg varchar(4000), @Errseverity int
    
        SELECT @ErrMsg = ERROR_MESSAGE(),
              @ErrSeverity = ERROR_SEVERITY()
    
        RAISERROR(@ErrMsg, @ErrSeverity, 1)     
    End Catch
    

    Hope this helps...

    0 讨论(0)
  • 2021-02-15 16:33

    I didn't use the raiseerror solution, because it failed as I didn't have admin permissions. I extended the noexec on/off solution with the transaction handling as follows:

    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
    

    Apparently the compiler "understands" the @finished variable in the IF, even if there was an error and the execution was disabled. However, the value is set to 1 only if the execution was not disabled. Hence I can nicely commit or rollback the transaction accordingly.

    0 讨论(0)
  • 2021-02-15 16:35
    SET XACT_ABORT ON
    BEGIN TRAN
    
    -- Batch 1
    
    GO
    
    if @@TRANCOUNT = 0 
    SET NOEXEC ON;
    GO
    
    -- Batch 2
    
    GO
    
    if @@TRANCOUNT = 0 
    SET NOEXEC ON;
    GO
    
    -- Batch 3
    
    GO
    
    if @@TRANCOUNT > 0 
    COMMIT
    GO
    
    0 讨论(0)
  • 2021-02-15 16:47

    Try using RETURN. this will exit the script or procedure immediately and will not execute any of the following statements. You can use this in conjunction with BEGIN, ROLLBACK and COMMIT TRANSACTION statements to undo any data damage:

        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
    
    0 讨论(0)
  • 2021-02-15 16:49

    When the error occurs, the transaction is rolled back automatically, and the current batch is aborted.

    Execution continues into the next batch, however. So all the stuff in the batches after the error gets executed. And then when you check for errors later, you try to rollback an already rolled back transaction.

    Also, to stop the entire script, not just the current batch, you should use:

    raiserror('Error description here', 20, -1) with log
    

    See my answer here for details on that one.

    So you need to check for @error after each batch, I think something like this should work:

    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
    
    0 讨论(0)
提交回复
热议问题