在批处理文件中使用 SQLCMD,如何解析响应并检查错误?
Using SQLCMD in a batch file, how can I parse the response and check for an error?
我正在使用 SQLCMD 获取 table 中的行数,但我也想知道查询是否遇到错误。
我使用的 sqlcmd 如下所示:
sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%"
如果有效,它将 return:
-----------
10205
(1 rows affected)
(注意,在我没有指定的列名 ------ 上方有一个空行。)
如果我传入不存在的 table,我会得到以下响应:
Msg 208, Level 16, State 1, Server devServer, Line 1
Invalid object name 'dbo.no_table'.
因为我有 -b 标志,所以我可以检查 ERRORLEVEL 的值(在本例中为 1)。
为了存储计数变量,我一直在使用以下行:
for /F %%i in ('sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%" ^| findstr /r "[^(][0-9]"') do SET /a rec_count=%%i
for之后,%errorlevel%returns 0。即使在do里面,errorlevel也是0。
有什么简单的方法可以运行 sqlcmd,如果没有错误就存储计数,如果有错误就打印两行?
errorlevel
似乎没有被设置的原因是 for
命令正在成功执行,无论它循环执行的代码如何执行。因此,您只能与同一行(for 循环括号内)的 sqlcmd 命令设置的错误级别进行交互。
您应该可以在 sqlcmd 命令后使用 ||
(双管道)。如果前一个命令失败,||
之后的任何代码只会 运行。示例:
notACommand || echo test
将return“test
”。而以下将仅输出 "a command
":
echo a command || echo test
我无法对其进行测试,但类似以下内容应该适合您:
for /F "EOL=(" %%i in ('sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%" ^|^| echo fail') do (
SET rec_count=%%i
)
if "%rec_count%"=="fail" echo SQL command failed
如果输出与您所说的完全一致,那么您不需要 findstr 命令 - 只需将 (
左括号设置为 for 循环中的 EOL 字符,这样您就可以有效地删除 "(1 rows affected)
" 行。您可能希望以不同方式使用这些变量,但这只是您判断 sqlcmd 命令是否失败的一种方式。
至于输出错误 - 一个糟糕的解决方案是再次 运行 相同的 sqlcmd 命令。类似于以下内容:
set command=sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%"
for /F "EOL=(" %%i in ('%command% ^|^| echo fail') do SET rec_count=%%i
if "%rec_count%"=="fail" (%command%) else echo rec_count is %rec_count%
请注意,我在设置 rec_count 变量时删除了 /a 开关,因为它现在可以设置为一个单词。
由 FOR /F 执行的命令通过新的 CMD session 隐式执行。例如,使用for /f %a in ('echo hello') do ...
,执行的命令变为C:\Windows\system32\cmd.exe /c echo hello
。
您的命令正确设置了 ERRORLEVEL,但是一旦 child CMD session 终止并且控制返回到您的批处理脚本,该值就会丢失。
所以 /b
选项对你没有任何好处,可以放弃。
您可以通过添加 -h -1
选项来隐藏 header 信息。
您可以通过在命令前加上 set nocount on;
来抑制 (1 rows affected)
消息
您可以添加 -r 1
选项使错误消息出现在 stderr 而不是 stdout 上。这将阻止 FOR /F 处理任何错误,并且错误消息将出现在屏幕上。
您可以在执行命令前清除rec_count 变量。如果有错误,它将保持未定义状态,否则如果没有错误,它将包含计数。
set "rec_count="
for /f %%A in (
'sqlcmd -S %server% -U %user% -P %pass% -h -1 -r 1 -Q "set nocount on;select count(*) from %table%"'
) do set "rec_count=%%A"
if not defined rec_count echo There was an error!
您可能会考虑的另一件事是将 SQLCMD 识别的环境变量用于您的服务器、用户名和密码。这样您就不必使用 -S、-U 或 -P 选项。如果您的批处理脚本运行许多 SQLCMD 命令,这将特别方便。
set "sqlcmdServer=YourServer"
set "sqlcmdUser=YourUserName"
set "sqlcmdPassword=YourPassword"
set "rec_count="
for /f %%A in (
'sqlcmd -h -1 -r 1 -Q "set nocount on;select count(*) from %table%"'
) do set "rec_count=%%A"
if not defined rec_count echo There was an error!
我正在使用 SQLCMD 获取 table 中的行数,但我也想知道查询是否遇到错误。
我使用的 sqlcmd 如下所示:
sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%"
如果有效,它将 return:
-----------
10205
(1 rows affected)
(注意,在我没有指定的列名 ------ 上方有一个空行。)
如果我传入不存在的 table,我会得到以下响应:
Msg 208, Level 16, State 1, Server devServer, Line 1
Invalid object name 'dbo.no_table'.
因为我有 -b 标志,所以我可以检查 ERRORLEVEL 的值(在本例中为 1)。
为了存储计数变量,我一直在使用以下行:
for /F %%i in ('sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%" ^| findstr /r "[^(][0-9]"') do SET /a rec_count=%%i
for之后,%errorlevel%returns 0。即使在do里面,errorlevel也是0。
有什么简单的方法可以运行 sqlcmd,如果没有错误就存储计数,如果有错误就打印两行?
errorlevel
似乎没有被设置的原因是 for
命令正在成功执行,无论它循环执行的代码如何执行。因此,您只能与同一行(for 循环括号内)的 sqlcmd 命令设置的错误级别进行交互。
您应该可以在 sqlcmd 命令后使用 ||
(双管道)。如果前一个命令失败,||
之后的任何代码只会 运行。示例:
notACommand || echo test
将return“test
”。而以下将仅输出 "a command
":
echo a command || echo test
我无法对其进行测试,但类似以下内容应该适合您:
for /F "EOL=(" %%i in ('sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%" ^|^| echo fail') do (
SET rec_count=%%i
)
if "%rec_count%"=="fail" echo SQL command failed
如果输出与您所说的完全一致,那么您不需要 findstr 命令 - 只需将 (
左括号设置为 for 循环中的 EOL 字符,这样您就可以有效地删除 "(1 rows affected)
" 行。您可能希望以不同方式使用这些变量,但这只是您判断 sqlcmd 命令是否失败的一种方式。
至于输出错误 - 一个糟糕的解决方案是再次 运行 相同的 sqlcmd 命令。类似于以下内容:
set command=sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%"
for /F "EOL=(" %%i in ('%command% ^|^| echo fail') do SET rec_count=%%i
if "%rec_count%"=="fail" (%command%) else echo rec_count is %rec_count%
请注意,我在设置 rec_count 变量时删除了 /a 开关,因为它现在可以设置为一个单词。
由 FOR /F 执行的命令通过新的 CMD session 隐式执行。例如,使用for /f %a in ('echo hello') do ...
,执行的命令变为C:\Windows\system32\cmd.exe /c echo hello
。
您的命令正确设置了 ERRORLEVEL,但是一旦 child CMD session 终止并且控制返回到您的批处理脚本,该值就会丢失。
所以 /b
选项对你没有任何好处,可以放弃。
您可以通过添加 -h -1
选项来隐藏 header 信息。
您可以通过在命令前加上 set nocount on;
(1 rows affected)
消息
您可以添加 -r 1
选项使错误消息出现在 stderr 而不是 stdout 上。这将阻止 FOR /F 处理任何错误,并且错误消息将出现在屏幕上。
您可以在执行命令前清除rec_count 变量。如果有错误,它将保持未定义状态,否则如果没有错误,它将包含计数。
set "rec_count="
for /f %%A in (
'sqlcmd -S %server% -U %user% -P %pass% -h -1 -r 1 -Q "set nocount on;select count(*) from %table%"'
) do set "rec_count=%%A"
if not defined rec_count echo There was an error!
您可能会考虑的另一件事是将 SQLCMD 识别的环境变量用于您的服务器、用户名和密码。这样您就不必使用 -S、-U 或 -P 选项。如果您的批处理脚本运行许多 SQLCMD 命令,这将特别方便。
set "sqlcmdServer=YourServer"
set "sqlcmdUser=YourUserName"
set "sqlcmdPassword=YourPassword"
set "rec_count="
for /f %%A in (
'sqlcmd -h -1 -r 1 -Q "set nocount on;select count(*) from %table%"'
) do set "rec_count=%%A"
if not defined rec_count echo There was an error!