9

I have a table MyTable created by

CREATE TABLE MyTable
(
    [ID] [bigint] IDENTITY(1,1) NOT NULL,
    [Type] [int] NOT NULL,
    [CreatedDate] [datetime] NOT NULL,
    [ModifiedDate] [datetime] NOT NULL,
)

I want to check if a column exists in my table, and if it does, I want to copy the data to a different column, then drop the old column, like this:

IF (SELECT COLUMNPROPERTY(OBJECT_ID('MyTable'), 'Timestamp', 'Precision')) IS NOT NULL
BEGIN
    UPDATE [dbo].[MyTable]
    SET [CreatedDate] = [Timestamp]

    ALTER TABLE [dbo].[MyTable]
    DROP COLUMN [Timestamp]
END
GO

However, when I try to run this I get an error:

Invalid column name 'Timestamp'

How can I accomplish what I'm trying to do?

8
  • so what does the select columnproperty(...) sub-query return? I'm guessing it isn't null, so your update runs, and since timestamp really DOESN'T exist, you get that error. Commented Jul 18, 2016 at 18:48
  • why mysql tag .. your code seems sqlserver .. remove the improper tags please Commented Jul 18, 2016 at 18:51
  • Seems like a wild west way of programming to me Commented Jul 18, 2016 at 18:51
  • I think your example is not correct, Commented Jul 18, 2016 at 18:56
  • 1
    sql statements in a sproc are evaluated for correctness when the sproc itself is compiled. That means your if() doesn't really apply when the sproc is parsed and your table is checke for a Timestamp field AT TIME OF COMPILE. You'd have to do it as dynamic sql. e.g. sql = 'UPDATE ..'; exec @sql-type thing Commented Jul 18, 2016 at 18:59

2 Answers 2

15

This is a compilation issue.

If the table doesn't exist when you compile the batch all works fine as the statements referencing the table are subject to deferred compile. However for a preexisting table you will hit this problem as it tries to compile all statements and balks at the non existent column.

You can push the code into a child batch so it is only compiled if that branch is hit.

IF (SELECT COLUMNPROPERTY(OBJECT_ID('MyTable'), 'Timestamp', 'Precision')) IS NOT NULL
BEGIN
EXEC('
    UPDATE [dbo].[MyTable]
    SET [CreatedDate] = [Timestamp]

    ALTER TABLE [dbo].[MyTable]
    DROP COLUMN [Timestamp]
    ')
END
GO

If you are just trying to rename the column

EXEC sys.sp_rename 'dbo.MyTable.[TimeStamp]' , 'CreatedDate', 'COLUMN'

Would be easier though (from a position where the CreatedDate column doesn't exist).

Sign up to request clarification or add additional context in comments.

Comments

0

You have to first create the [Timestamp] column with an ALTER TABLE statement.

Then the rest should run.

EDIT based on comment (I know this info is duplicated elsewhere on SO, but I couldn't find it):

Ok, the IF condition in SQL Server unfortunately does not allow you to ignore code that does not parse. What is happening is that SQL Server is looking at your command, and parsing every statement to make sure it is valid.

When it does this, SQL Server isn't smart enough to figure out that the invalid statement (the UPDATE that requires the presence of [TimeStamp]) will not be reached if there is no [TimeStamp].

In other words, you can't write a SQL command that expects a column that doesn't exist EVEN IF you nest that command in an IF condition that won't be reached. SQL Server will parse the entire statement and not allow it to run BEFORE it tests the IF condition.

A commonly used Work arounds for this is Dynamic SQL, which SQL Server can't pre-parse, so it won't try.

1 Comment

The point is to check if my system has already been altered to delete this column. Readding it is not the point. IF it still exists, that means my script hasn't been run before. If the column doesn't exist, I want it to skip this entire block of code

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.