我有一个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.
答案 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"
)