Как я могу выполнить команду обновления, только если условие истинно? - PullRequest
3 голосов
/ 04 августа 2009

Я работаю над сценарием обновления БД, который должен удалить столбец (эта часть проста). Прежде чем я смогу удалить столбец, я хочу взять значение и переместить его в другой столбец, который уже существует.

Я пытаюсь достичь идемпотентности с помощью своего сценария, в котором я, похоже, терплю неудачу. У меня есть такой код ...

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

Независимо от того, что я делаю, запрос UPDATE всегда выполняется, даже если условие ложно, что приводит к ошибкам. Что мне нужно сделать, чтобы предотвратить выполнение этого запроса, если мое начальное условие ложно? Оператор ALTER TABLE под ним запускается только в том случае, если условие истинно.

1 Ответ

12 голосов
/ 04 августа 2009

Я предполагаю, что когда вы говорите, что «запрос ОБНОВЛЕНИЯ всегда выполняется, что вызывает ошибки», вы имеете в виду, что вы получаете ошибку:

Msg 207, Level 16, State 1 Line 6
Invalid column name 'Column1'.

Это не потому, что запрос выполняется - это ошибка синтаксического анализа. Весь оператор IF анализируется SQL Server до его выполнения, и в операторе UPDATE происходит сбой, поскольку Column1 больше не существует. Это также дает сбой в операторе ALTER TABLE, но SQL Server показывает только первую ошибку.

Кстати, именно поэтому пример Шеннон работает - поскольку оба ее блока IF анализируются одновременно, второй, который напоминает ваш, очень хорошо анализирует, потому что во время анализа сценария столбец все еще существует. Я подозреваю, что если Шеннон снова запустит свой сценарий (за исключением частей создания таблицы), появится та же ошибка.

Чтобы обойти это, вам просто нужно использовать динамический SQL - он не анализируется до тех пор, пока строка не будет запущена. Вы запускаете динамический SQL с помощью команды EXEC и передаете ей строку, которую хотите выполнить, например:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...