Тестовый Столбец существует, Добавьте Столбец и Столбец Обновления

Я пытаюсь записать сценарий обновления базы данных SQL Server. Я хочу протестировать на существование столбца в таблице, затем если оно не существует, добавляет столбец со значением по умолчанию и наконец обновляет тот столбец на основе текущего значения другого столбца в той же таблице. Я хочу, чтобы этот сценарий был выполним многократно, в первый раз обновив таблицу, и на последующих выполнениях должен быть проигнорирован сценарий. Мой сценарий в настоящее время похож на следующее:

IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_NAME = 'PurchaseOrder' AND COLUMN_NAME = 'IsDownloadable')
BEGIN

ALTER TABLE [dbo].[PurchaseOrder] ADD [IsDownloadable] bit NOT NULL DEFAULT 0

UPDATE [dbo].[PurchaseOrder] SET [IsDownloadable] = 1 WHERE [Ref] IS NOT NULL

END

SQL Server возвращает ошибку "Недопустимое имя столбца 'IsDownloadable'", т.е. Я должен фиксировать DDL, прежде чем я смогу обновить столбец. Я попробовал различные перестановки, но я нигде не не становлюсь быстрым.

49
задан David Clarke 3 May 2010 в 12:43
поделиться

2 ответа

Этот сценарий не будет успешно выполнен, если столбец уже существует, то есть именно тогда, когда он не нужен.

Сценарии SQL должны быть разобраны, прежде чем они могут быть выполнены. Если столбец не существует на момент разбора сценария, то разбор будет неудачным. Не имеет значения, что ваши сценарии создадут столбец позже; синтаксический анализатор не имеет возможности узнать об этом.

Вам нужно вставить GO оператор (пакетный разделитель), если вы хотите получить доступ к столбцу, который вы только что добавили. Однако, как только вы это сделаете, вы больше не сможете поддерживать поток управления или переменные из предыдущей партии - это все равно, что запустить два отдельных сценария. Это затрудняет одновременное выполнение DDL и DML, условно, в одно и то же время.

Самый простой обходной путь, который я бы, вероятно, рекомендовал вам, поскольку ваш DML не очень сложен, это использовать динамический SQL, который парсер не будет пытаться разобрать до "времени выполнения":

IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_NAME = 'PurchaseOrder' AND COLUMN_NAME = 'IsDownloadable')
BEGIN

    ALTER TABLE [dbo].[PurchaseOrder] ADD 
        [IsDownloadable] bit NOT NULL DEFAULT 0

    EXEC sp_executesql
        N'UPDATE [dbo].[PurchaseOrder] SET [IsDownloadable] = 1 WHERE [Ref] IS NOT NULL'

END
81
ответ дан 7 November 2019 в 11:46
поделиться

Попробуйте добавить оператор «GO» после ALTER TABLE.

Для меня это было новостью, но здесь говорится, что все операторы в пакете (предшествующие GO) скомпилированы в один план запроса.) Без GO в SQL весь план является фактически один запрос.

РЕДАКТИРОВАТЬ: Поскольку GO выдает синтаксическую ошибку (что мне показалось странным), я создал нечто подобное и обнаружил, что это сработало

declare @doUpdate bit;

SELECT @doUpdate = 0;

IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_NAME = 'PurchaseOrder' AND COLUMN_NAME = 'IsDownloadable')
BEGIN
 SELECT @doUpdate=1
END

IF @doUpdate<>0 
   ALTER TABLE [dbo].[PurchaseOrder] ADD [IsDownloadable] bit NOT NULL DEFAULT 0

IF @doUpdate<>0
  UPDATE [dbo].[PurchaseOrder] SET [IsDownloadable] = 1 WHERE [Ref]=0

COMMIT TRAN
-1
ответ дан 7 November 2019 в 11:46
поделиться
Другие вопросы по тегам:

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