0

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

3 回答 3

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 )"

不同的是感叹号 (!) 消失了。这解释了为什么比较总是评估为假,因为比较与您期望的完全相反。

我最终发现,由于之前执行了 SETLOCAL ENABLEDELAYEDEXPANSION,调用此脚本的 CMD.EXE 当前处于延迟的环境变量扩展模式。当 CMD.EXE 处理该行时,! 字符标记扩展的开始,因此它会自动将其剥离。但是,下一个字符是等号字符 (=),这在环境变量中是不允许的,因此处理会立即取消变量扩展,转而处理该字符。所以只有 = 字符被设置为 OSQL.EXE 的参数。

正确的解决方案是在调用脚本之前立即执行 SETLOCAL DISABLEDELAYEDEXPANSION,然后执行 ENDLOCAL。

于 2013-06-26T22:55:36.223 回答
1

此外,在运行 osql/sqlcmd 的批处理中使用 "LIKE '%mytext%'" 的语法可能会出现问题,因为您需要加倍处理那些讨厌的百分号!但是,当您在命令提示符下测试它时,它当然可以正常工作。今天早些时候我花了大约一个小时试图调试它。为什么我没有立即看到并理解这个问题?不幸的是,我的记忆越来越像我妈妈的每一天......痴呆症在家庭中流行;-(

于 2015-05-21T17:04:00.600 回答
0

我会将其更改EXITEXIT /B

EXIT终止CMD会话。

exit /b optionalerrorlevelnumber终止当前批次,可选择返回错误级别。

于 2013-06-26T17:33:30.043 回答