我使用SQLCMD获取表中的行数,但我也想知道查询是否遇到错误。
我使用的sqlcmd看起来像这样:
sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%"
如果有效,它将返回:
-----------
10205
(1 rows affected)
(注意,-------上面有一个空白行,列名I我没有指定。)
如果我传入的表格不存在,我会收到以下回复:
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%返回0.即使在do内,errorlevel也是0。
有没有简单的方法来运行sqlcmd,如果没有错误则存储计数,如果有错误则打印两行?
答案 0 :(得分:5)
由FOR / F执行的命令通过新的CMD会话隐式执行。例如,对于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!
您可能考虑的另一件事是使用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!
答案 1 :(得分:1)
errorlevel
似乎没有设置的原因是因为for
命令正在成功执行,无论它循环执行的代码如何执行。因此,您只能与sqlcmd命令在同一行(在for循环括号内)设置的errorlevel进行交互。
您应该能够在sqlcmd命令之后使用||
(双管道)。 ||
之后的任何代码只有在前一个命令失败时才会运行。例如:
notACommand || echo test
将返回“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开关,因为它现在可以设置为单词。