Условная логика в сценарии PostDeployment.sql с использованием SQLCMD - PullRequest
52 голосов
/ 22 августа 2011

Я использую проект базы данных SQL 2008 (в Visual Studio) для управления схемой и начальными данными испытаний для моего проекта.Проект atabase использует последующее развертывание, которое включает в себя ряд других сценариев, использующих синтаксис SQLCMD «: r».

Я хотел бы иметь возможность условно включать определенные файлы на основе переменной SQLCMD.Это позволит мне несколько раз запустить проект с нашей ночной сборкой, чтобы настроить различные версии базы данных с различными конфигурациями данных (для мультитенантной системы).

Я пробовал следующее:

IF ('$(ConfigSetting)' = 'Configuration1')
  BEGIN
    print 'inserting specific configuration' 
:r .\Configuration1\Data.sql
  END
ELSE
  BEGIN
    print 'inserting generic data' 
:r .\GenericConfiguration\Data.sql
  END

Но я получаю ошибку компиляции: SQL01260: Произошла фатальная ошибка синтаксического анализатора: Script.PostDeployment.sql

Кто-нибудь видел эту ошибку или сумел настроить их после развертываниясценарий быть гибким в этом смысле?Или я полностью ошибаюсь?

Спасибо, Роб

PS Я также пытался изменить это так, чтобы путь к файлу был переменной, похоже на этот пост .Но это дает мне ошибку, говоря, что путь неверен.

Ответы [ 6 ]

35 голосов
/ 25 августа 2011

UPDATE

Теперь я обнаружил, что приведенный выше синтаксис if / else не работает для меня, потому что некоторые из моих связанных скриптов требуют оператора GO. По сути,: r просто импортирует скрипты, так что это становится недействительным синтаксисом.

Если вам нужен оператор GO в связанных сценариях (как и я), то нет простого способа обойти это, я закончил тем, что создал несколько сценариев после развертывания, а затем изменил свой проект, чтобы перезаписать основной сценарий после развертывания в время сборки в зависимости от конфигурации сборки. Сейчас я делаю то, что мне нужно, но, похоже, должен быть более легкий путь!

Для тех, кому нужно то же самое - Я нашел этот пост полезным

Итак, в моем проекте у меня есть следующие файлы после развертывания:

  • Script.PostDeployment.sql (пустой файл, который будет заменен)
  • Default.Script.PostDeployment.sql (ссылки на скрипты, необходимые для стандартной конфигурации данных)
  • Configuration1.Script.PostDeployment.sql (ссылки на скрипты, необходимые для конкретной конфигурации данных)

Затем я добавил следующее в конец файла проекта (щелкните правой кнопкой мыши, чтобы выгрузить, а затем щелкните правой кнопкой мыши на правке):

  <Target Name="BeforeBuild">
      <Message Text="Copy files task running for configuration: $(Configuration)" Importance="high" />
      <Copy Condition=" '$(Configuration)' == 'Release' " SourceFiles="Scripts\Post-Deployment\Default.Script.PostDeployment.sql" DestinationFiles="Scripts\Post-Deployment\Script.PostDeployment.sql" OverwriteReadOnlyFiles="true" />
      <Copy Condition=" '$(Configuration)' == 'Debug' " SourceFiles="Scripts\Post-Deployment\Default.Script.PostDeployment.sql" DestinationFiles="Scripts\Post-Deployment\Script.PostDeployment.sql" OverwriteReadOnlyFiles="true" />
      <Copy Condition=" '$(Configuration)' == 'Configuration1' " SourceFiles="Scripts\Post-Deployment\Configuration1.Script.PostDeployment.sql" DestinationFiles="Scripts\Post-Deployment\Script.PostDeployment.sql" OverwriteReadOnlyFiles="true" />
  </Target>

Наконец, вам необходимо настроить соответствующие конфигурации сборки в решении.

Кроме того, для любого, кто пробует другие способы обхода, я также попытался без удачи:

  1. Создание события пост-сборки для копирования файлов вместо того, чтобы взламывать файл проекта XML. я не мог заставить это работать, потому что я не мог сформировать правильный путь к файлу сценария после развертывания. Эта проблема с подключением описывает проблему

  2. Использование переменных для пути к сценарию для передачи в команду: r. Но я столкнулся с несколькими ошибками при таком подходе.

17 голосов
/ 08 декабря 2015

Мне удалось обойти проблему, используя метод noexec .

Итак, вместо этого:

IF ('$(ConfigSetting)' = 'Configuration1')
 BEGIN
    print 'inserting specific configuration' 
    :r .\Configuration1\Data.sql
 END

Я отменил условное выражение и установил NOEXEC ON чтобы пропустить импортированные операторы таким образом:

IF ('$(ConfigSetting)' <> 'Configuration1')
    SET NOEXEC ON

:r .\Configuration1\Data.sql

SET NOEXEC OFF

Убедитесь, что вы отключили его, если хотите выполнить любые последующие операторы.

15 голосов
/ 14 января 2012

Вот как я обрабатываю условное развертывание в процессе после развертывания, чтобы развернуть тестовые данные для отладки, но не для конфигурации выпуска.

Сначала в обозревателе решений откройте папку свойств проекта и щелкните правой кнопкой мыши, чтобы добавить новый файл SqlCmd.variables.

Назовите файл Debug.sqlcmdvars.

В файле добавьте свои пользовательские переменные, а затем добавьте конечную переменную с именем $(BuildConfiguration) и установите значение Debug.

Повторите процесс для создания Release.sqlcmdvars, установив $(BuildConfiguration) в Release.

Теперь настройте ваши конфигурации: Откройте страницу свойств проекта на вкладке «Развертывание». В верхнем раскрывающемся списке установите для конфигурации значение «Отладка». В нижнем раскрывающемся списке (переменные команды Sql) установите для этого файла значение Properties \ Debug.sqlcmdvars.

Повторите для выпуска как: В верхнем раскрывающемся списке выберите конфигурацию Release. В нижнем раскрывающемся списке (переменные команды Sql) установите для этого файла значение Properties \ Release.sqlcmdvars.

Теперь в вашем файле Script.PostDeployment.sql вы можете указать условную логику, например:

IF 'Debug' = '$(BuildConfiguration)'
BEGIN
PRINT '***** Creating Test Data for Debug configuration *****';
:r .\TestData\TestData.sql
END

В обозревателе решений щелкните правой кнопкой мыши решение верхнего уровня и откройте Configuration Manager. Вы можете указать, какая конфигурация активна для вашей сборки. Вы также можете указать конфигурацию в командной строке MSBUILD.EXE.

Вот и все - теперь у ваших сборок разработчика есть тестовые данные, но нет вашей релизной сборки!

8 голосов
/ 29 августа 2012

Как Роб работал, операторы GO не разрешены в связанных сценариях SQL, поскольку это вложит их в операторы BEGIN / END.

Однако у меня есть другое решение для его - если возможно,удалите все операторы GO из ссылочных сценариев и поместите один после оператора END:

IF '$(DeployTestData)' = 'True'
BEGIN
    :r .\TestData\Data.sql
END
GO -- moved from Data.sql

Обратите внимание, что я также создал новую переменную в моем sqlcmdvars файле с именем $(DeployTestData), который позволяет включать / выключать развертывание тестового сценария.

2 голосов
/ 28 декабря 2016

Меня вдохновило решение Роба Берда.Однако я просто использую события сборки для замены сценариев после развертывания на основе выбранной конфигурации сборки.

  1. У меня есть один пустой «фиктивный» сценарий после развертывания.
  2. Я установилсобытие перед сборкой для замены этого «фиктивного» файла на основе выбранной конфигурации сборки (см. прилагаемое изображение).
  3. Я установил событие после сборки, чтобы поместить «фиктивный» файл обратно после сборкизакончил (см. прикрепленное изображение).Причина в том, что я не хочу генерировать изменения в управлении изменениями после сборки.

Build Events setup example

2 голосов
/ 05 февраля 2016

Я нашел взлом из блога MSDN , который работал довольно хорошо. Хитрость заключается в том, чтобы записать команды в файл временного сценария, а затем выполнить этот сценарий. В основном эквивалент динамического SQL для SQLCMD.

-- Helper newline variable
:setvar CRLF "CHAR(13) + CHAR(10)"
GO
-- Redirect output to the TempScript.sql file
:OUT $(TEMP)\TempScript.sql

IF ('$(ConfigSetting)' = 'Configuration1')
  BEGIN
    PRINT 'print ''inserting specific configuration'';' + $(CRLF)   
    PRINT ':r .\Configuration1\Data.sql' + $(CRLF)
  END
ELSE
  BEGIN
    PRINT 'print ''inserting generic data'';' + $(CRLF) 
    PRINT ':r .\GenericConfiguration\Data.sql' + $(CRLF)
  END
GO
-- Change output to stdout
:OUT stdout

-- Now execute the generated script
:r $(TEMP)\TempScript.sql
GO

Файл TempScript.sql будет содержать либо:

print 'inserting specific configuration';   
:r .\Configuration1\Data.sql

или

print 'inserting generic data';
:r .\GenericConfiguration\Data.sql

в зависимости от значения $(ConfigSetting) и не будет проблем с операторами GO и т. Д. При его выполнении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...