Cuando ocurre el error, la transacción se revierte automáticamente y el lote actual se aborta.
Sin embargo, la ejecución continúa en el siguiente lote. Así que se ejecutan todas las cosas en los lotes después del error. Y luego, cuando verifica si hay errores más tarde, intenta revertir una transacción ya revertida.
Además, para detener todo el script, no solo el lote actual, debe usar:
raiserror('Error description here', 20, -1) with log
Consulte mi respuesta aquí para obtener detalles sobre eso.
Por lo tanto, debe buscar @error
después de cada lote, creo que algo como esto debería 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