I have a migration script written in Transact-SQL which is using transactions in order to have a proper rollback if something goes wrong during the execution. Unfortunately, thi
Some errors roll back the transaction. Don't bother figuring out which ones, because there's no simple rule.
A multi-batch script should have a single error handler scope that rolls back the transaction on error, and commits at the end. In TSQL you can do this with dynamic sql, eg
BEGIN TRANSACTION
BEGIN TRY
EXEC('
-- Create a table with two nullable columns
CREATE TABLE [dbo].[t1](
[id] [nvarchar](36) NULL,
[name] [nvarchar](36) NULL
)
')
EXEC('
-- add one row having one NULL column
INSERT INTO [dbo].[t1] VALUES(NEWID(), NULL)
')
-- set one column as NOT NULLABLE
-- this fails because of the previous insert
EXEC('
ALTER TABLE [dbo].[t1] ALTER COLUMN [name] [nvarchar](36) NOT NULL
')
EXEC('
-- create a table as next action, so that we can test whether the rollback happened properly
CREATE TABLE [dbo].[t2](
[id] [nvarchar](36) NOT NULL
)
')
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK;
THROW;
END CATCH
With SQLCMD you can use the -b
option to abort the script on error.