У меня есть сценарий TSQL, который делает много корректировок структуры базы данных, но не действительно безопасно просто позволить ему пройти, когда что-то перестало работать.
ясно дать понять вещи:
то, что я имею, является чем-то в следующем порядке
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 пытается выполнить каждый оператор после того, как ошибка произошла. (Я заметил это, когда новые таблицы обнаружились, когда я не ожидал их, потому что это должно было откатывать),
При возникновении ошибки транзакция автоматически откатывается, а текущий пакет прерывается.
Однако выполнение продолжается в следующем пакете. Итак, все вещи в пакетах после ошибки выполняются. А затем, когда вы позже проверяете наличие ошибок, вы пытаетесь откатить уже откатанную транзакцию.
Кроме того, чтобы остановить весь сценарий, а не только текущий пакет, вы должны использовать:
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
Вы можете попробовать что-то вроде этого ... Если вы используете блок 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
Надеюсь, это поможет ...