我通过批处理文件自动化各种EXE,包括调用现有的批处理文件,该文件又通过OSQL.exe执行各种TSQL语句。
现有批处理文件正常。但是,当我的批处理文件调用时,对osql.exe的调用失败,导致批处理文件退出。
:check_user_privs
%OSQLPATH% %CONNECTSTRING% -S "%SERVER_INSTANCE%" -d "%DBNAME%" -Q "DECLARE @userName varchar(100) ; set @userName = user_name() ; IF IS_SRVROLEMEMBER ('sysadmin') != 1 RAISERROR ('This user ''%s'' is not a member of the ''sysadmin'' group.' , 16 , 127 , @userName )" > /nul
if errorlevel 1 (
echo ** ERROR - The user is NOT a sysadmin member on "%SERVER_INSTANCE%" - Exiting ** 1
echo.
pause
exit
)
可以说,错误发生了。在ECHO ON时,第一行变为:
"C:\Program Files\Microsoft SQL Server\100\Tools\Binn\OSQL.EXE" -U"ADMIN" -P"PASSWORD" -S "SQL_SRVR10" -d "DB01" -Q "DECLARE @userName varchar(100) ; set @userName = user_name() ; IF IS_SRVROLEMEMBER ('sysadmin') != 1 RAISERROR ('This user ''ADMIN'' is not a member of the ''sysadmin'' group.' , 16 , 127 , @userName )" > /nul
当我直接从命令行或我自己的批处理文件调用脚本时,这一行是相同的。
我手动捕获了从批处理文件调用此批处理文件时设置的环境变量。然后我在命令行手动设置它们,然后手动运行批处理文件。没有责任。
我更改了TSQL语句,只输出函数IS_SRVROLEMEMBER()的返回值。从我的脚本和命令行调用,输出都是相同的 - “1”:
"C:\Program Files\Microsoft SQL Server\100\Tools\Binn\OSQL.EXE" -U"ADMIN" -P"PASSWORD" -S "SQL_SRVR10" -d "DB01" -Q "SELECT IS_SRVROLEMEMBER ('sysadmin')"
答案 0 :(得分:1)
好吧,我花了一些时间在这上面,我注意到如果我使用CMD.EXE / C或START / B / WAIT来调用另一个脚本,则不会发生错误。所以它肯定是关于导致问题的CMD.EXE进程的状态。
另外,我决定将每一行的ECHO转换为文本文件。我注意到有一个微妙的区别:
ECHO "C:\Program Files\Microsoft SQL Server\100\Tools\Binn\OSQL.EXE" -U"ADMIN" -P"PASSWORD" -S "SQL_SRVR10" -d "DB01" -Q "DECLARE @userName varchar(100) ; set @userName = user_name() ; IF IS_SRVROLEMEMBER ('sysadmin') != 1 RAISERROR ('This user ''ADMIN'' is not a member of the ''sysadmin'' group.' , 16 , 127 , @userName )" > out.txt
当你看out.txt时,它包含:
"C:\Program Files\Microsoft SQL Server\100\Tools\Binn\OSQL.EXE" -U"ADMIN" -P"PASSWORD" -S "SQL_SRVR10" -d "DB01" -Q "DECLARE @userName varchar(100) ; set @userName = user_name() ; IF IS_SRVROLEMEMBER ('sysadmin') = 1 RAISERROR ('This user ''ADMIN'' is not a member of the ''sysadmin'' group.' , 16 , 127 , @userName )"
区别在于感叹号(!)已消失。这解释了为什么比较总是评估为假,因为比较与您期望的完全相反。
我最终发现正在发生的事情是调用此脚本的CMD.EXE当前处于延迟环境变量扩展模式,这是由于之前执行了SETLOCAL ENABLEDELAYEDEXPANSION。当CMD.EXE处理该行时,!字符标志着扩展的开始,因此它会自动将其剥离。但是,下一个字符是等号(=),这在环境变量中是不允许的,因此处理会立即取消变量扩展,而是处理该字符。因此,只有=字符被设置为OSQL.EXE的参数。
正确的解决方案是在调用脚本之前,执行SETLOCAL DISABLEDELAYEDEXPANSION,然后执行ENDLOCAL。
答案 1 :(得分:1)
此外,您可能会遇到使用" LIKE'%mytext%'"在一个运行osql / sqlcmd的批处理中,因为你需要在那些讨厌的百分号上加倍! 但是,当您在命令提示符中测试它时,它当然可以正常工作。 我今天早些时候花了大约一个小时尝试调试 。 为什么我没有立即看到并理解这个问题? 不幸的是,我的记忆每天都变得像妈妈一样......痴呆症在家庭中运行; - (
答案 2 :(得分:0)
我将EXIT
更改为EXIT /B
EXIT
终止CMD
会话。
exit /b optionalerrorlevelnumber
终止当前批处理,可选择返回错误级别。