Dan Herbert
Dan Herbert

Reputation: 103377

How can I only execute an update command if a condition is true?

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

Answers (1)

Steve Broberg
Steve Broberg

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

Related Questions