从批处理文件调用的批处理文件调用时,OSQL中的TSQL语句失败

时间:2013-06-26 16:08:15

标签: sql-server-2008 tsql batch-file osql

我通过批处理文件自动化各种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')"

3 个答案:

答案 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终止当前批处理,可选择返回错误级别。