如何使用批处理中的参数运行sqlcmd并将返回值赋给变量?

时间:2015-04-05 20:06:57

标签: sql-server windows batch-file cmd

我有一个MS SQL脚本,它接受两个变量并执行它应该做的事情,返回一个值。

在我的批处理文件中,我按如下方式调用此脚本,并获得我期望的输出。

sqlcmd -v ALM_Domain=%dom% ProjectName=%proj% /h-1 -S %DB% -E -C -i GetDBNameForDomainProject.sql

但是,我需要在后续处理中使用查询返回的值,并决定将返回值分配给变量。为此,我使用了以下构造

for /F usebackq %%a IN (`sqlcmd -v ALM_Domain=%dom% ProjectName=%proj% /h-1 -S %DB% -E -C -i GetDBNameForDomainProject.sql`) do (
    set DBNAME=%%a
)

我得到以下错误:

Sqlcmd: 'NCA ProjectName SIM': Invalid argument. Enter '-?' for help.

请注意' ='标志似乎消失了。帮助for命令状态:

最后,您可以使用FOR / F命令来解析a的输出 命令。你可以通过在文件集之间建立文件集来实现 括号后引用的字符串。它将被视为一个命令 line,传递给子CMD.EXE并捕获输出 进入内存并解析,好像它是一个文件。

如果我尝试使用:

for /F %%a IN ('sqlcmd -v "ALM_Domain=%dom% ProjectName=%proj%" /h-1 -S %DB% -E -C -i GetDBNameForDomainProject.sql') do (
    set DBNAME=%%a
)

我明白了:

Sqlcmd: 'ALM_DOMAIN=NCA ProjectName=SIM': Invalid argument.

1 个答案:

答案 0 :(得分:3)

与您的问题无关 - 使用FOR / F执行命令时很少需要USEBACKQ。它的主要用途是从名称中包含空格或有毒字符的文件中读取,这需要保留引号。但双引号通常表示字符串值,因此需要USEBACKQ

for /f "usebackq" %%A in ("file name with spaces.txt") do ...

如果您正在执行命令,那么您只需要正常的单引号,而不使用USEBACKQ选项

for /f %%A in ('someCommand.exe') do ...

你当然可以使用USEBACKQ进行反击,但我认为没有任何好处。

现在针对您的实际问题 - 您已注意到解析器已将您的=转换为<space>。这是批处理解析器的“功能”,它必须将命令解析为由CMD /C执行的字符串。解析器将=,;<tab><space><0xFF>视为令牌分隔符,以及任何连续的令牌分隔符字符串转换为单<space>

解决方案是将整个命令括在双引号内(在表示命令的外部单引号内),或者转义问题字符。在您的情况下,我相信您可以使用双引号。

for /F %%a IN ('"sqlcmd -v ALM_Domain=%dom% ProjectName=%proj% /h-1 -S %DB% -E -C -i GetDBNameForDomainProject.sql"') do (
  set "DBNAME=%%a"
)

您的案例不是问题,但如果您的命令已使用双引号,则替代方法是转义=

for /F %%a IN ('sqlcmd -v ALM_Domain^=%dom% ProjectName^=%proj% /h-1 -S %DB% -E -C -i GetDBNameForDomainProject.sql') do (
  set "DBNAME=%%a"
)