Reputation: 103377
I'm working on a DB upgrade script that needs to drop a column (that part's easy). Before I can drop the column, I want to take the value and move it into another column that already exists.
I'm trying to acheive idempotence with my script, which is where I seem to be failing. I have code like this...
IF EXISTS (SELECT *
FROM sys.all_columns
WHERE sys.all_columns.object_id = OBJECT_ID(N'[dbo].[MyTable]')
AND sys.all_columns.name = 'Column1')
BEGIN
UPDATE [dbo].[MyTable]
SET [Column2] = [Column1]
ALTER TABLE [dbo].[MyTable]
DROP COLUMN [Column1]
END
No matter what I do, the UPDATE
query is always executed, even if the condition is false, which causes errors. What do I need to do to prevent this query from being run if my initial condition is false? The ALTER TABLE
statement below it only gets run if the condition is true.
Upvotes: 3
Views: 4240
Reputation: 4394
I'm guessing that when you say "the UPDATE query is always executed, which causes errors", you mean that you're getting the error:
Msg 207, Level 16, State 1 Line 6
Invalid column name 'Column1'.
This is not because the query is executing - this is a parsing error. The entire IF statement gets parsed by SQL Server before it is executed, and it is failing on the UPDATE statement because Column1 no longer exists. It's also failing on the ALTER TABLE statement, but SQL Server only shows you the first error.
Incidentally, this is why Shannon's example works - since both of her IF blocks are parsed at once, the second one that resembles yours parses just fine, because at the time the script is parsed, the column still exists. I suspect that if Shannon were to run her script again (minus the create table parts), the same error would appear.
To get around this, you just need to use dynamic SQL - it is not parsed until the line is actually run. You run dynamic SQL using the EXEC command, and you pass it the string you want to execute, like so:
IF EXISTS (SELECT *
FROM sys.all_columns
WHERE sys.all_columns.object_id = OBJECT_ID(N'[dbo].[MyTable]')
AND sys.all_columns.name = 'Column1')
BEGIN
EXEC('UPDATE [dbo].[MyTable] SET [Column2] = [Column1]')
EXEC('ALTER TABLE [dbo].[MyTable] DROP COLUMN [Column1]')
END
Upvotes: 12