This:
use test;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRANSACTION;
EXEC sp_RENAME 'table1.asd' , 'ads', 'COLUMN';
INSERT INTO table1 (ads) VALUES (12);
COMMIT
is a simple example that demonstrates what I would like to do.
I want to alter the table in some way and perform inserts/deletes in one transaction (or other modifications to the table).
The problem is that the results from sp_RENAME are never immediately visible to the INSERT statement. I’ve played with different transaction isolation levels – it’s always the same (therefore the transaction never commits).
Normally I would just use GO statements for this to be in separate batches, but I need that in one batch, because…
My real task is to write a script that adds identity and FK to a table (this requires creating another table with the new schema, performing identity inserts from the old one, renaming the table and applying constraints). I need to play it safe – if any part of the procedure fails I have to rollback the whole transaction. This is why I wanted to do something like this:
BEGIN TRAN
--some statement
IF (@@ERROR <> 0) GOTO ERR_HANDLER
-- some other statement
IF (@@ERROR <> 0) GOTO ERR_HANDLER
COMMIT TRAN
RETURN 0
ERR_HANDLER:
PRINT 'Unexpected error occurred!'
ROLLBACK TRAN
RETURN 1
Since labels work only inside a batch I cannot use GO statements.
So how can I:
- make statements(ie. ALTER TABLE, sp_RENAME) have an immediate effect ?
or
- write the whole solution some other way so that it is safe to run in production DB ?
The issue is that the parsing of the batch fails when it encounters the reference to the renamed column so the entire batch never gets executed – not that the effects of the transaction are not visible.
You can put your statements referencing the new name of the column in an
EXEC('')block to defer compilation until after the column is renamed.