存储过程调用xp_cmdshell执行带参命令提示varchar类型错误
问题原因
报错的核心原因是传入系统存储过程xp_cmdshell的命令参数实际类型为nvarchar,和该过程要求的varchar类型不匹配:
- SQL Server中
CONCAT()函数的返回值类型由输入参数的最高优先级数据类型决定,nvarchar类型优先级高于varchar - 存储过程定义的三个入参
@LoginID、@Country、@FullName均为nvarchar(120)类型,因此CONCAT()拼接后的返回值默认是nvarchar(max)类型 - 虽然声明了
@cmd变量为varchar(max),但部分SQL Server版本下,动态拼接生成的nvarchar结果赋值给varchar变量时的隐式转换不会被xp_cmdshell识别,直接触发类型校验报错。
修复方法
拼接命令字符串时显式将nvarchar类型的入参转换为varchar,确保最终传入xp_cmdshell的参数为严格的varchar类型即可。
调整后的可正常执行的存储过程代码如下:
ALTER PROCEDURE [dbo].[AddMSTRUser] @LoginID nvarchar(120), @Country nvarchar(120), @FullName nvarchar(120) AS -- xp_cmdshell在老版本SQL Server中对varchar(max)兼容不佳,用varchar(8000)通用性更强 DECLARE @cmd varchar(8000); SET @cmd = CONCAT( 'MASysMgr.exe -w "C:\User.smw" -l "C:\cache.txt" -p ', '"LoginID=', CAST(@LoginID AS varchar(120)), '" ', '"Country=', CAST(@Country AS varchar(120)), '" ', '"FullName=', CAST(@FullName AS varchar(120)), '"' ) EXECUTE master..xp_cmdshell @cmd;
兼容低版本SQL Server的写法
如果使用的是SQL Server 2008R2及更早版本(无内置CONCAT()函数),可以用+运算符拼接字符串,同样需要显式做类型转换:
ALTER PROCEDURE [dbo].[AddMSTRUser] @LoginID nvarchar(120), @Country nvarchar(120), @FullName nvarchar(120) AS DECLARE @cmd varchar(8000); SET @cmd = 'MASysMgr.exe -w "C:\User.smw" -l "C:\cache.txt" -p ' + '"LoginID=' + CAST(@LoginID AS varchar(120)) + '" ' + '"Country=' + CAST(@Country AS varchar(120)) + '" ' + '"FullName=' + CAST(@FullName AS varchar(120)) + '"' EXECUTE master..xp_cmdshell @cmd;
注:上述代码已经给原写法中未加引号的
C:\User.smw路径补上了双引号,避免后续路径包含空格时出现命令执行错误。
内容的提问来源于stack exchange,提问作者Ugurcan Kaya
相关产品推荐
相关产品推荐

