Reputation: 8669
I am doing a data migration and I am currently implementing a reverse-script for our worst case scenario. I might be a little bit tired now but I can´t get my head around this thing - so maybe you can help.
I have the following SQL:
IF NOT EXISTS(SELECT * FROM sys.columns WHERE Name = N'FileId' AND Object_ID = Object_ID(N'[FileData]'))
AND EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'FileData'
AND COLUMN_NAME = 'FileDataId')
BEGIN
SELECT 1;
--ALTER TABLE [FileData] ADD [FileId] [uniqueidentifier] NULL
--ALTER TABLE [FileData] DROP CONSTRAINT PK_FileData
--UPDATE [FileData] SET [FileData].[FileId] = [File].[FileId]
--FROM [FileData] INNER JOIN [File] on [FileData].FileDataId = [File].FileData
--ALTER TABLE [FileData] ALTER COLUMN [FileId] [uniqueidentifier] NOT NULL
--ALTER TABLE [FileData] ADD CONSTRAINT PK_FileData PRIMARY KEY (FileId)
END
ELSE
BEGIN
SELECT 0;
END
Running the query above will consistently return a 0 - which is correct, since the FileName
column does exist and the FileDataId
does not. So far so good.
When I remove the first select
statement and uncomment the alter and update code. I get the error:
Invalid column name 'FileDataId'
Query I run after uncommenting
IF NOT EXISTS(SELECT * FROM sys.columns WHERE Name = N'FileId' AND Object_ID = Object_ID(N'[FileData]'))
AND EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'FileData'
AND COLUMN_NAME = 'FileDataId')
BEGIN
ALTER TABLE [FileData] ADD [FileId] [uniqueidentifier] NULL
ALTER TABLE [FileData] DROP CONSTRAINT PK_FileData
UPDATE [FileData] SET [FileData].[FileId] = [File].[FileId]
FROM [FileData] INNER JOIN [File] on [FileData].FileDataId = [File].FileData
ALTER TABLE [FileData] ALTER COLUMN [FileId] [uniqueidentifier] NOT NULL
ALTER TABLE [FileData] ADD CONSTRAINT PK_FileData PRIMARY KEY (FileId)
END
ELSE
BEGIN
SELECT 0;
END
My question:
How come I consistently get the same false
result from the IF-statement but when I uncomment the code in the true
-clause it suddenly gets entered. Am I completely missing something here?
Upvotes: 1
Views: 140
Reputation: 239734
SQL Server wants to compile the entire batch before it executes it. It fails to compile it because the column doesn't exist, and so it never gets as far as executing the IF
statement.
You have to use dynamic SQL so that it doesn't attempt to compile the statements referencing the column until after you've verified its existence.
IF NOT EXISTS(SELECT * FROM sys.columns WHERE Name = N'FileId' AND Object_ID = Object_ID(N'[FileData]'))
AND EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'FileData'
AND COLUMN_NAME = 'FileDataId')
BEGIN
EXEC('ALTER TABLE [FileData] ADD [FileId] [uniqueidentifier] NULL')
EXEC('ALTER TABLE [FileData] DROP CONSTRAINT PK_FileData')
EXEC('UPDATE [FileData] SET [FileData].[FileId] = [File].[FileId]
FROM [FileData] INNER JOIN [File] on [FileData].FileDataId = [File].FileData')
EXEC('ALTER TABLE [FileData] ALTER COLUMN [FileId] [uniqueidentifier] NOT NULL')
EXEC('ALTER TABLE [FileData] ADD CONSTRAINT PK_FileData PRIMARY KEY (FileId)')
END
ELSE
BEGIN
SELECT 0;
END
Upvotes: 3