Выход и откат все в сценарии на ошибке

У меня есть сценарий 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

только для иллюстрирования, с чем я работаю..., не может войти в специфические особенности теперь, проблему...

Когда я представляю ошибку (чтобы протестировать, если вещи откатываются), я получаю оператор, что ROLLBACK TRANSACTION не мог найти соответствующий BEGIN TRANSACTION. Это приводит меня полагать, что что-то, когда ДЕЙСТВИТЕЛЬНО неправильно и транзакция был уже уничтожен. то, что я также заметил, - то, что сценарий не полностью выходил на ошибке, и таким образом DID пытается выполнить каждый оператор после того, как ошибка произошла. (Я заметил это, когда новые таблицы обнаружились, когда я не ожидал их, потому что это должно было откатывать),

8
задан Jan W. 3 January 2012 в 15:01
поделиться

2 ответа

При возникновении ошибки транзакция автоматически откатывается, а текущий пакет прерывается.

Однако выполнение продолжается в следующем пакете. Итак, все вещи в пакетах после ошибки выполняются. А затем, когда вы позже проверяете наличие ошибок, вы пытаетесь откатить уже откатанную транзакцию.

Кроме того, чтобы остановить весь сценарий, а не только текущий пакет, вы должны использовать:

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

См. мой ответ здесь , чтобы узнать подробности об этом.

Итак, вам нужно проверять @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
7
ответ дан 5 December 2019 в 12:08
поделиться

Вы можете попробовать что-то вроде этого ... Если вы используете блок Try ... Уровень ошибки 16 (или большая часть ошибок приложения) немедленно передает управление блоку CATCH без выполнение любых дальнейших операторов в блоке try ...

    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

Надеюсь, это поможет ...

0
ответ дан 5 December 2019 в 12:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: