SQL Server sqlcmd setvar 取决于所选数据库

Ben*_*oit 3 sql-server sqlcmd

我现在正在使用sqlcmd一段时间来更新我们项目的数据库。

在我们使用这样的脚本之前:

:setvar relativepath D:\Project1\Sql
:r $(relativepath)\Tables\CreateTable1.sql
:r $(relativepath)\SP\Table1.sql
Run Code Online (Sandbox Code Playgroud)

这是在开发和发布期间更新数据库的好方法。

但是现在我们使用不同的目录,这取决于我们是在开发分支还是生产分支(Subversion)。

我们希望避免错误,以防有人通过根据所选数据库名称设置路径将脚本提交到错误的目录。像这样的事情:

:setvar relativepath "D:\Project1\Prod\Sql"
if (DB_name() = 'Project1' OR DB_name() = 'Project1_Dev')
begin
    :setvar relativepath "D:\Project1\Dev\Sql"
end
Run Code Online (Sandbox Code Playgroud)

我找不到办法做到这一点。有人有想法吗?

[更新] 解决方案:(坦克到 wBob)

我有一个名为的脚本: setRelativePath.sql

:out D:\Project1\SQL\Temp\temp.sql
go

declare @bdName varchar(15) = DB_name()
--Here the print got saved to D:\Project1\SQL\Temp\temp.sql
if @bdName = 'Project1' OR @bdName = 'Project1_DEV'
    print ':setvar relativepath D:\Project1\DEV\Sql'
else if @bdName = 'Project1_PROD'
    print ':setvar relativepath D:\Project1\PROD\Sql'
else 
    raiserror( 'Unknown value (%s) for sqlcmd variable relativepath.', 16, 1, @bdName )

go
:out stdout
go

!!REM Read the file to execute the setvar statement
:r D:\Project1\SQL\Temp\temp.sql
go


--Here the print is displayed then we execute the script
print 'Relative path set to $(relativepath)'
go
Run Code Online (Sandbox Code Playgroud)

然后我在我的脚本文件中使用它:

:r D:\Project1\SQL\setRelativePath.sql
:r $(relativepath)\SP\SomeStoredProcedure.sql
Run Code Online (Sandbox Code Playgroud)

D:\Project1\SQL\ 在后备箱里。

relativepathvarriable可使用的内SomeStoredProcedure.sql给。

此脚本确保我们不会将开发脚本应用于生产并在我们将开发合并到生产时删除步骤。

wBo*_*Bob 5

您不能将sqlcmd模式命令与 T-SQL 条件逻辑混合使用。有一种方法可以做到这一点,但至于是否可取是另一回事。

此技术涉及重定向stdout、写出文件并在sqlcmd模式下执行该文件以获得您需要的效果:

:out d:\temp\temp.sql
go

declare @x varchar(5) = 'dev'

if @x = 'dev'
    print ':setvar testVar dev'
else if @x = 'prod'
    print ':setvar testVar prod'
else raiserror( 'Unknown value (%s) for sqlcmd variable testVar.', 16, 1, @x )
go
:out stdout
go

!!REM Read the file to execute the setvar statement
:r d:\temp\temp.sql
go

select '$(testVar)' env

print 'it looks like this is the $(testvar) environment after all'
go
Run Code Online (Sandbox Code Playgroud)

显然,运行此方法的进程将需要访问临时目录和文件,并且此方法存在相关权限(和风险)。重定向输出时,GO 的位置​​很重要。

至于用法,我不会特别建议。我们对此进行了试验(因此我知道这种技术),但远离它,转而支持数据库项目(为您处理所有这些)或可重新运行的(幂等)脚本。不是在父脚本中加载条件逻辑,而是将每个对象脚本构建为可使用“如果不存在”检查重新运行,例如:

if not exists ( the table )
  create the table

if not exists ( a column )
  add the column
Run Code Online (Sandbox Code Playgroud)

那么我们是在 dev 还是 prod 中运行,或者我们运行脚本多少次都无关紧要。一段时间后,这些可能会变得有点笨拙。