Условная логика в PostDeployment.sql script с использованием SQLCMD
Я использую проект базы данных SQL 2008 (в visual studio) для управления схемой и исходными тестовыми данными для моего проекта. Проект atabase использует пост-развертывание, которое включает в себя ряд других скриптов с использованием синтаксиса SQL: ". 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
Кто-нибудь видел эту ошибку или сумел настроить их postdeployment script, чтобы быть гибким таким образом? Или я об этом совершенно не согласен?
Спасибо,
Rob
P.S. Я также попытался изменить это так, чтобы путь к файлу был переменным, похожим на этот пост. Но это дает мне ошибку, говоря, что путь неверный.
Ответы
Ответ 1
UPDATE
Теперь я обнаружил, что синтаксис if/else выше не работает для меня, потому что некоторые из моих связанных скриптов требуют инструкции GO. По существу: r просто импортирует скрипты inline, поэтому это становится недопустимым sytax.
Если вам нужен оператор GO в связанных сценариях (как и я), тогда нет никакого простого способа обойти это, я закончил создание нескольких сценариев пост-развертывания, а затем изменил свой проект, чтобы перезаписать основной пост-отказ script во время сборки в зависимости от конфигурации сборки. Это сейчас делает то, что мне нужно, но похоже, что должен быть более простой способ!
Для тех, кому нужно одно и то же - Я нашел это сообщение полезным
Итак, в моем проекте у меня есть следующие файлы для развертывания после публикации:
- 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>
Наконец, вам нужно будет настроить соответствующие конфигурации сборки в решении.
Кроме того, для тех, кто пробовал другие работы, я также пробовал следующее без везения:
-
Создание события post build для копирования файлов вместо того, чтобы взломать файл проекта XML. я не мог заставить это работать, потому что я не мог сформировать правильный путь к файлу post-развертывания script. Эта проблема с подключением описывает проблему
-
Использование переменных для пути script для перехода к команде: r. Но при таком подходе я столкнулся с несколькими ошибками.
Ответ 2
Вот как я обрабатываю условное развертывание в процессе после развертывания для развертывания тестовых данных для конфигурации Debug, но не Release.
Сначала в проводнике решений откройте папку свойств проекта и щелкните правой кнопкой мыши, чтобы добавить новый файл SqlCmd.variables.
Назовите файл Debug.sqlcmdvars
.
Внутри файла добавьте свои пользовательские переменные, а затем добавьте конечную переменную с именем $(BuildConfiguration)
и установите значение Debug.
Повторите этот процесс, чтобы создать Release.sqlcmdvars, установив $(BuildConfiguration)
для выпуска.
Теперь настройте свои конфигурации:
Откройте страницу свойств проекта на вкладке "Развернуть".
В верхнем раскрывающемся списке настройте конфигурацию как Debug.
В нижнем раскрывающемся списке (переменные команды Sql) задайте файл в Properties\Debug.sqlcmdvars.
Повторить для выпуска как:
В верхней раскрывающемся списке установите конфигурацию для выпуска.
В нижнем раскрывающемся списке (переменные команды 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.
Теперь вы можете: теперь ваши сборки разработчика содержат тестовые данные, но не вашу сборку релизов!
Ответ 3
Мне удалось решить проблему с помощью метода 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
Убедитесь, что вы отменили его, если вы хотите выполнить любые последующие утверждения.
Ответ 4
Как выяснил Роб, инструкции GO не разрешены в связанных скриптах SQL, так как это может вложить его в инструкции BEGIN/END.
Однако у меня есть другое решение для его - если возможно, удалить любые инструкции GO из ссылочных сценариев и поместить один из них после инструкции END:
IF '$(DeployTestData)' = 'True'
BEGIN
:r .\TestData\Data.sql
END
GO -- moved from Data.sql
Обратите внимание, что я также создал новую переменную в моем файле sqlcmdvars с именем $(DeployTestData), который позволяет мне включать/отключать тестирование script.
Ответ 5
Я нашел взломать блог MSDN, который работал достаточно хорошо. Хитрость заключается в том, чтобы написать команды в файл temp script, а затем выполнить это script. В основном эквивалент динамического 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
и т.д. проблем не будет.
Ответ 6
Я был вдохновлен решением Роба Берда. Тем не менее, я просто использую Build Events для замены сценариев пост-развертывания на основе выбранной конфигурации сборки.
- У меня есть одно пустое развертывание "dummy" post script.
- Я установил событие pre-build для замены этого файла "dummy" на основе выбранной конфигурации сборки (см. прикрепленное изображение).
- Я установил событие post-build для размещения файла "dummy" после завершения сборки (см. прикрепленное изображение). Причина в том, что я не хочу создавать изменения в управлении изменениями после сборки.
![Build Events setup example]()