T-SQL «повторно работоспособный» сценарии обновления базы данных - столбец удаление

голоса
1

Для нашей базы данных SQL Server, мы используем схему управления версиями для отслеживания обновления схемы. Идея заключается в том, что вы должны быть в состоянии выполнить этот сценарий, чтобы привести схему с любой предыдущей версии до текущей версии. Запуск мастер-скрипт снова должен выполнять только самые новые обновления схемы.

Структура сценария выглядит так:

 SELECT @Installed = InstallDate FROM SystemSchemaVersion WHERE Major=1 AND Minor=0 AND Patch=0
 IF (@Installed IS NULL)
 BEGIN
    ...
    INSERT IGNORE  INTO SystemSchemaVersion (Major, Minor, Patch, InstallDate) VALUES (1, 0, 0, GetDate())
 END
 ELSE PRINT 'Version 1.0.0 was already installed on ' + Convert(varchar(10), @Installed)  

 SELECT @Installed = InstallDate FROM SystemSchemaVersion WHERE Major=1 AND Minor=0 AND Patch=1
 IF (@Installed IS NULL)
 BEGIN
    ...
    INSERT IGNORE  INTO SystemSchemaVersion (Major, Minor, Patch, InstallDate) VALUES (1, 0, 1, GetDate())
 END
 ELSE PRINT 'Version 1.0.1 was already installed on ' + Convert(varchar(10), @Installed)

Как правило, это работает очень хорошо. Тем не менее, мы столкнулись с проблемой, когда обновление схемы Drops столбца, который включен в предыдущем INSERT IGNORE; то есть, у нас есть что-то вроде этого:

 SELECT @Installed = InstallDate FROM SystemSchemaVersion WHERE Major=1 AND Minor=0 AND Patch=0
 IF (@Installed IS NULL)
 BEGIN
    INSERT IGNORE  [foo] ([a], [b], [OrganizationId]) VALUES (N'a', N'b', N'1');
    INSERT IGNORE  INTO SystemSchemaVersion (Major, Minor, Patch, InstallDate) VALUES (1, 0, 0, GetDate());
 END
 ELSE PRINT 'Version 1.0.0 was already installed on ' + Convert(varchar(10), @Installed)  

 SELECT @Installed = InstallDate FROM SystemSchemaVersion WHERE Major=1 AND Minor=0 AND Patch=1
 IF (@Installed IS NULL)
 BEGIN
    ALTER TABLE [foo] DROP COLUMN [OrganizationId];
    INSERT IGNORE  INTO SystemSchemaVersion (Major, Minor, Patch, InstallDate) VALUES (1, 0, 1, GetDate());
 END
 ELSE PRINT 'Version 1.0.1 was already installed on ' + Convert(varchar(10), @Installed)

Это хорошо работает в первый раз, она выполняется; версия 1.0.1 выполняется, а столбец удаляется. Тем не менее, запустив сценарий вторых выходов времени:

    Msg 207, Level 16, State 1, Line 7118
    Неверное имя столбца «OrganizationId».

То есть, даже если ВСТАВИТЬ ИГНОРИРУЙТЕ внутри блока версии 1.0.0 не выполняются, это еще разобрано и генерация недопустимых ошибок столбца.

Любые предложения о том, как обойти это? В идеале я хотел бы защитить ВСТАВИТЬ ИГНОРИРУЙТЕ с условным, так что это даже не разбирается, но не кажется, что происходит. Я мог бы динамически выполнять ВСТАВИТЬ ИГНОРИРУЙТЕ сек внутри sp_executesql () звонки, но я предпочел бы не (потребует много модернизации).

Благодаря --

--Энди

Задан 27/08/2009 в 01:51
источник пользователем
На других языках...                            


4 ответов

голоса
1

Хорошо, я неправильно прочитал вопрос изначально. :-)

Если вы измените вставки строк из:

INSERT IGNORE  [foo] ([a], [b], [OrganizationId]) VALUES (N'a', N'b', N'1');

чтобы:

exec('INSERT IGNORE  [foo] ([a], [b], [OrganizationId]) VALUES (''a'', ''b'', ''1'')');

Вы не должны иметь эту проблему, так как SQL «текст» внутри Exec не будет разобран до Exec () на самом деле называется.

Ответил 27/08/2009 в 02:40
источник пользователем

голоса
1

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

Если вы разделите его с заявлениями GO, то вы должны найти систему повторно оценить каждый раздел, как она приходит к нему.

обкрадывать

Ответил 27/08/2009 в 02:08
источник пользователем

голоса
0

Вы пробовали динамический Sql? К сожалению, анализатор будет проверять весь сценарий перед его запуском, поэтому любой неправильный столбец остановит выполнение.

Ответил 27/08/2009 в 02:22
источник пользователем

голоса
0

Мы используем практически идентичные настройки, чтобы иметь дело с версиями схемы.

В общем, ваш подход полностью звук. Мы эксплуатируем с этой общей установкой в ​​течение нескольких лет. В основном, для обработки любых деструктивных или не совместимые изменений схемы, мы бежим патчи как часть автоматизированной CruiseControl.NET сборки.

Таким образом, наша сборка базы данных выглядит следующим образом ...

  • Восстановление из резервной копии текущей версии PRODUCTION.
  • Проверьте версию восстановленной БД
  • Выполнить все патчи (они названы в соответствии с соглашением с использованием major.minor.sql), которые позже, чем версия, указанной в [Версии] таблице.

Таким образом, мы не можем восстановить весь день без каких-либо проблем, независимо от того, что делает патч. Это также гарантирует, что когда мы разворачивать к ПРОИЗВОДСТВУ нет никаких проблем, так как мы уже развернуты по PRODUCTION дб 1000x в процессе разработки.

Ответил 27/08/2009 в 02:12
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more