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