Вопрос по sql-server-2008, sql, if-statement – SQL-оператор IF игнорируется

2

У меня длинный сценарий, и я хотел бы иметь возможность просто запускать весь файл, когда мне нужно, и не беспокоиться о том, что его части уже запущены. Но приведенный ниже сценарий доставляет мне проблемы. По какой-то причине он проходит мимо оператора IF, даже если столбцы «EntityID» и «EntityType»; не существует, и в этом случае он не должен пройти через оператор IF. Может кто-нибудь сказать мне, что не так?

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'Notes' AND COLUMN_NAME IN ('EntityId', 'EntityType'))
BEGIN
    BEGIN TRANSACTION
        --Delete notes where EntityType and EntityID are both NULL
        DELETE FROM [dbo].[Notes]
        WHERE [EntityId] = NULL 
        AND [EntityType] = NULL
        --Delete notes where the corresponding contact or account has been deleted.
        OR [ID] IN (9788, 10684, 10393, 10718, 10719)

        --Populate new columns with all existing data
        UPDATE [dbo].[Notes]
        SET [AccountId] = [EntityId]
        WHERE [EntityType] = 1

        UPDATE [dbo].[Notes]
        SET [ContactId] = [EntityId]
        WHERE [EntityType] = 2

        --Delete EntityId and EntityType columns from the Notes table
        ALTER TABLE [dbo].[Notes]
        DROP COLUMN [EntityId], [EntityType]
    COMMIT
END
GO

Скрипт для таблицы

CREATE TABLE [dbo].[Notes](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [AnnotationID] [uniqueidentifier] NULL,
    [CreatedBy] [int] NULL,
    [CreatedDate] [datetime] NULL,
    [NoteText] [ntext] NULL,
    [OriginalAnnotationID] [uniqueidentifier] NULL,
    [Active] [bit] NULL,
    [ContactId] [int] NULL,
    [AccountId] [int] NULL,
 CONSTRAINT [PK_Notes] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

ALTER TABLE [dbo].[Notes]  WITH CHECK ADD  CONSTRAINT [FK_Account_ID] FOREIGN KEY([AccountId])
REFERENCES [dbo].[Account] ([ID])
GO

ALTER TABLE [dbo].[Notes] CHECK CONSTRAINT [FK_Account_ID]
GO

ALTER TABLE [dbo].[Notes]  WITH CHECK ADD  CONSTRAINT [FK_ContactId_ID] FOREIGN KEY([ContactId])
REFERENCES [dbo].[Contact] ([ID])
GO

ALTER TABLE [dbo].[Notes] CHECK CONSTRAINT [FK_ContactId_ID]
GO

Ошибки:

Msg 207, Level 16, State 1, Line 6
Invalid column name 'EntityId'.
Msg 207, Level 16, State 1, Line 7
Invalid column name 'EntityType'.
Msg 207, Level 16, State 1, Line 12
Invalid column name 'EntityType'.
Msg 207, Level 16, State 1, Line 16
Invalid column name 'EntityType'.
возвращает false, только если ни один из столбцов не существует. Так что, если один или другой делает ... Tony Hopkinson
Да, я получаю то же самое, если я пытаюсьCREATE TABLE Notes([ID] int) затем попробуйте ваш сценарий (сократить толькоDELETE заявление). IIRC SQL Server будет игнорироватьIF операторов, когда он компилирует скрипт и будет компилировать каждый оператор, за исключением случаев, когда он ссылается на несуществующий объект, и в этом случае он будет подвергаться отложенной компиляции. Martin Smith
Вы должны создать правильный сценарий развертывания для каждой среды, IMHO. Имея большой сценарий и просто позволяя его частям потерпеть неудачу, мне кажется, что это очень случайно и подвержено ошибкам. Aaron Bertrand
Вы уверены, что столбцы не существуют? - попробуй засунутьselect заявление в вышеIF и посмотреть, что (если что-нибудь) это возвращает Jon Egerton
Также вы не можете сказатьWHERE something = NULL тебе нужно сказатьWHERE something IS NULL... Aaron Bertrand

Ваш Ответ

2   ответа
4

IF обрабатывается парсером во время разбора и игнорирует ли вашIF удастся. Это та же самая причина, по которой вы не можете:

IF 1 = 1
  CREATE TABLE #x(a INT);
ELSE
  CREATE TABLE #x(b INT);

Одним из обходных путей может быть использование динамического SQL:

IF EXISTS ...
BEGIN
  BEGIN TRANSACTION;

  DECLARE @sql NVARCHAR(MAX);

  SET @sql = N'
        DELETE FROM [dbo].[Notes]
        WHERE [EntityId] IS NULL 
        AND [EntityType] IS NULL
        --Delete notes where the corresponding contact or account has been deleted.
        OR [ID] IN (9788, 10684, 10393, 10718, 10719)

        --Populate new columns with all existing data
        UPDATE [dbo].[Notes]
        SET [AccountId] = [EntityId]
        WHERE [EntityType] = 1

        UPDATE [dbo].[Notes]
        SET [ContactId] = [EntityId]
        WHERE [EntityType] = 2

        --Delete EntityId and EntityType columns from the Notes table
        ALTER TABLE [dbo].[Notes]
        DROP COLUMN [EntityId], [EntityType]';

    EXEC sp_executesql @sql;

    COMMIT TRANSACTION;
END

Но вы все равно должны быть уверены, чтоboth колонны есть.

да, это работает. Спасибо Jmh2013
0

что проблема в том, что один из столбцов существует, но не оба. Попробуйте следующее:

IF 2 = (SELECT count(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'Notes' AND COLUMN_NAME IN ('EntityId', 'EntityType')) 
Возможно ли, что у вас есть представление в другой схеме с тем же именем (Примечания)?
Ни один из двух столбцов не существует прямо сейчас. Я попробовал ваше предложение и получаю ту же самую ошибку:invalid column name 'EntityId' Jmh2013

Похожие вопросы