使用 SQLCMD 的 PostDeployment.sql 脚本中的条件逻辑
我正在使用 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
有没有人看到此错误或设法将其部署后脚本配置为以这种方式灵活?还是我完全以错误的方式处理这件事?
谢谢, 罗布·
P.S.我还尝试对此进行更改,以便文件的路径是一个变量, 类似于这篇文章。但这给了我一个错误,说路径不正确。
I am using a SQL 2008 database project (in visual studio) to manage the schema and initial test data for my project. The atabase project uses a post deployment which includes a number of other scripts using SQLCMD's ":r " syntax.
I would like to be able to conditionally include certain files based on a SQLCMD variable. This will allow me to run the project several times with our nightly build to setup various version of the database with different configurations of the data (for a multi-tenant system).
I have tried the following:
IF ('$(ConfigSetting)' = 'Configuration1')
BEGIN
print 'inserting specific configuration'
:r .\Configuration1\Data.sql
END
ELSE
BEGIN
print 'inserting generic data'
:r .\GenericConfiguration\Data.sql
END
But I get a compilation error:
SQL01260: A fatal parser error occurred: Script.PostDeployment.sql
Has anyone seen this error or managed to configure their postdeployment script to be flexible in this way? Or am I going about this in the wrong way completely?
Thanks,
Rob
P.S. I've also tried changing this around so that the path to the file is a variable, similar to this post. But this gives me an error saying that the path is incorrect.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
更新
我现在发现上面的 if/else 语法对我不起作用,因为我的一些链接脚本需要 GO 语句。本质上 :r 只是内联导入脚本,所以这变成了无效的语法。
如果您需要在链接脚本中使用 GO 语句(就像我一样),那么没有任何简单的方法可以解决这个问题,我最终创建了几个部署后脚本,然后更改我的项目以在构建时覆盖主要部署后脚本,具体取决于关于构建配置。这现在正在做我需要的事情,但似乎应该有一个更简单的方法!
对于任何需要同样东西的人 - 我找到了这篇文章有用
因此,在我的项目中,我有以下部署后文件:
然后我将以下内容添加到项目文件的末尾(右键单击卸载,然后右键单击编辑):
最后,您需要在解决方案中设置匹配的构建配置。
另外,对于任何尝试其他解决方法的人,我也尝试了以下方法,但没有任何运气:
创建一个构建后事件来复制文件,而不必破解项目文件 XML。我无法让它工作,因为我无法形成部署后脚本文件的正确路径。 此连接问题描述了该问题< /a>
使用脚本路径变量传递给 :r 命令。但我在这种方法中遇到了一些错误。
UPDATE
I've now discovered that the if/else syntax above doesn't work for me because some of my linked scripts require a GO statement. Essentially the :r just imports the scripts inline, so this becomes invalid sytax.
If you need a GO statement in the linked scripts (as I do) then there isn't any easy way around this, I ended up creating several post deployment scripts and then changing my project to overwrite the main post depeployment script at build time depending on the build configuration. This is now doing what I need, but it seems like there should be an easier way!
For anyone needing the same thing - I found this post useful
So in my project I have the following post deployment files:
I then added the following to the end of the project file (right click to unload and then right click edit):
Finally, you will need to setup matching build configurations in the solution.
Also, for anyone trying other work arounds, I also tried the following without any luck:
Creating a post build event to copy the files instead of having to hack the project file XML. i couldn't get this to work because I couldn't form the correct path to the post deployment script file. This connect issue describes the problem
Using variables for the script path to pass to the :r command. But I came across several errors with this approach.
我设法使用noexec方法解决了这个问题。
因此,我不是这样:
我反转了条件并设置 NOEXEC ON 来跳过导入的语句:
如果要执行任何后续语句,请确保将其关闭。
I managed to work around the problem using the noexec method.
So, instead of this:
I reversed the conditional and set NOEXEC ON to skip over the imported statement(s) thusly:
Make sure you turn it back off if you want to execute any subsequent statements.
以下是我在部署后过程中处理条件部署的方式,以便为调试而非发布配置部署测试数据。
首先,在解决方案资源管理器中,打开项目属性文件夹,然后右键单击以添加新的 SqlCmd.variables 文件。
将文件命名为
Debug.sqlcmdvars
。在该文件中,添加自定义变量,然后添加名为
$(BuildConfiguration)
的最终变量,并将值设置为 Debug。重复此过程以创建 Release.sqlcmdvars,并将
$(BuildConfiguration)
设置为 Release。现在,配置您的配置:
打开“部署”选项卡的项目属性页面。
在顶部下拉列表中,将配置设置为“调试”。
在底部下拉菜单(Sql 命令变量)中,将文件设置为 Properties\Debug.sqlcmdvars。
重复发布:
在顶部下拉列表中,将配置设置为发布。
在底部下拉菜单(Sql 命令变量)中,将文件设置为 Properties\Release.sqlcmdvars。
现在,在 Script.PostDeployment.sql 文件中,您可以指定条件逻辑,例如:
在解决方案资源管理器中,右键单击顶级解决方案并打开配置管理器。您可以指定哪个配置对您的构建处于活动状态。
您还可以在 MSBUILD.EXE 命令行上指定配置。
现在你的开发版本有测试数据,但没有你的发布版本!
Here's how I am handling conditional deployment within the post deployment process to deploy test data for the Debug but not Release configuration.
First, in solution explorer, open the project properties folder, and right-click to add a new SqlCmd.variables file.
Name the file
Debug.sqlcmdvars
.Within the file, add your custom variables, and then add a final variable called
$(BuildConfiguration)
, and set the value to Debug.Repeat the process to create a Release.sqlcmdvars, setting the
$(BuildConfiguration)
to Release.Now, configure your configurations:
Open up the project properties page to the Deploy tab.
On the top dropdown, set the configuration to be Debug.
On the bottom dropdown, (Sql command variables), set the file to Properties\Debug.sqlcmdvars.
Repeat for Release as:
On the top dropdown, set the configuration to be Release.
On the bottom dropdown, (Sql command variables), set the file to Properties\Release.sqlcmdvars.
Now, within your Script.PostDeployment.sql file, you can specify conditional logic such as:
In solution explorer, right click on the top level solution and open Configuration Manager. You can specify which configuration is active for your build.
You can also specify the configuration on the MSBUILD.EXE command line.
There you go- now your developer builds have test data, but not your release build!
正如 Rob 所指出的,链接的 SQL 脚本中不允许使用 GO 语句,因为这会将其嵌套在 BEGIN/END 语句中。
然而,我有一个不同的解决方案 - 如果可能的话,从引用的脚本中删除任何 GO 语句,并在 END 语句后面放置一个:
请注意,我还在我的 sqlcmdvars 名为 $(DeployTestData) 的文件,它允许我打开/关闭测试脚本部署。
As Rob worked out, GO statements aren't allowed in the linked SQL scripts as this would nest it within the BEGIN/END statements.
However, I have a different solution to his - if possible, remove any GO statements from the referenced scripts, and put a single one after the END statement:
Note that I've also created a new variable in my sqlcmdvars file called $(DeployTestData) which allows me to turn on/off test script deployment.
我找到了 来自 MSDN 博客的 hack 效果相当好。诀窍是将命令写入临时脚本文件,然后执行该脚本。基本上相当于 SQLCMD 的动态 SQL。
然后,
TempScript.sql
文件将包含:或 ,
具体取决于
$(ConfigSetting)
的值,并且GO
语句不会出现问题等执行时。I found a hack from an MSDN blog which worked fairly well. The trick is to write the commands to a temp script file and then execute that script instead. Basically the equivalent of dynamic SQL for SQLCMD.
The
TempScript.sql
file will then contain either:or
depending on the value of
$(ConfigSetting)
and there will be no problems withGO
statements etc. when it is executed.我受到了 Rob Bird 解决方案的启发。但是,我只是使用构建事件来替换基于所选构建配置的部署后脚本。
I was inspired by Rob Bird's solution. However, I am simply using the Build Events to replace the post deployment scripts based on the selected build configuration.