在批处理文件中使用SQLCMD,如何解析响应并检查错误?

Dan*_*Dan 1 sql-server batch-file sqlcmd

我正在使用SQLCMD来获取表中的行数,但我也想知道查询是否遇到错误.

我使用的sqlcmd看起来像这样:

sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%"
Run Code Online (Sandbox Code Playgroud)

如果有效,它将返回:

-----------
      10205

(1 rows affected)
Run Code Online (Sandbox Code Playgroud)

(注意,-------上面有一个空行,我没有指定列名.)

如果我传入一个不存在的表,我得到以下响应:

Msg 208, Level 16, State 1, Server devServer, Line 1
Invalid object name 'dbo.no_table'.
Run Code Online (Sandbox Code Playgroud)

由于我有-b标志,我可以检查ERRORLEVEL的值(在本例中为1).

要存储count变量,我一直在使用以下行:

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
Run Code Online (Sandbox Code Playgroud)

在for之后,%errorlevel%返回0.即使在do内,errorlevel也是0.

是否有任何简单的方法来运行sqlcmd,如果没有错误则存储计数,如果有错误则打印两行?

dbe*_*ham 5

由FOR/F执行的命令通过新的CMD会话隐式执行.例如,with for /f %a in ('echo hello') do ...,执行的命令变为C:\Windows\system32\cmd.exe /c echo hello.

您的命令正确设置了ERRORLEVEL,但是一旦子CMD会话终止并且控制权返回到您的批处理脚本,该值就会丢失.

因此,该/b选项对您没有任何好处,可以放弃.

您可以通过添加-h -1选项来抑制标题信息.

您可以(1 rows affected)通过为命令添加前缀来禁止显示消息set nocount on;

您可以添加该-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!
Run Code Online (Sandbox Code Playgroud)

您可能考虑的另一件事是使用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!
Run Code Online (Sandbox Code Playgroud)