Quando o erro ocorre, a transação é revertida automaticamente e o lote atual é abortado.
A execução continua no próximo lote, no entanto. Portanto, todas as coisas nos lotes após o erro serem executadas. E então, quando você verifica os erros mais tarde, tenta reverter uma transação já revertida.
Além disso, para interromper todo o script, não apenas o lote atual, você deve usar:
raiserror('Error description here', 20, -1) with log
Consulte minha resposta aqui para detalhes sobre isso.
Portanto, você precisa verificar se há
@error
após cada lote, acho que algo assim deve funcionar: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