在扩展存储过程-exec master..xp_cmdshell 中传递/使用标量变量

Posted

技术标签:

【中文标题】在扩展存储过程-exec master..xp_cmdshell 中传递/使用标量变量【英文标题】:Passing/Using Scalar variable in extended stored procedure-exec master..xp_cmdshell 【发布时间】:2021-04-25 12:30:38 【问题描述】:

我必须在不使用导出向导的情况下将 Student 表中的数据导出为 CSV。如果我们硬编码注册号,下面的脚本可以正常工作,但是当使用变量@registration_no 时会报错:必须声明标量变量。在打印@cmd 时,registration_no 正确替换为 101。似乎 @registration 超出了 exec master..xp_cmdshell 的范围

 Begin
    Declare @registration_no as int
    set @registration_no = 101
    Declare @cmd as nvarchar(4000)
    set @cmd = 'sqlcmd -s, -W -Q "set nocount on; select * from [Student_Management].[dbo].[Student] where registration_no = @registration_no " | findstr /v /c:"-" /b > "d:\student.csv" '  
    exec master..xp_cmdshell @cmd
END

【问题讨论】:

SQL 不是脚本语言,文字字符串中的变量不会被批处理中的变量值替换。 SELECT '@Variable' 不返回存储在变量中的值,它返回 literal 字符串 '@Variable'. @larnu 能否请您提供解决方案,我也尝试过存储过程,但无法成功。我想将许多表的数据导出到 CSV,并且必须提供一个参数(如 registration_no)来过滤数据。但是需要一个相同的脚本并且不能使用向导 您需要将变量中包含的值嵌入到您构建的字符串中。就这么简单。类似 set @cmd = '.... where registration_no = ' + cast(@registration_no as varchar(11)) + ... @SMor 仍然得到:必须声明标量变量“@registration_no”。将 set 命令更改为: set @ cmd = 'sqlcmd -s, -W -Q "set nocount on; select * from [Student_Management].[dbo].[Student] where registration_no = +cast(@registration_no as int)" | findstr /v /c:"-" /b > "d:\student.csv"' OR set @ cmd = 'sqlcmd -s, -W -Q "set nocount on; select * from [Student_Management].[dbo] .[学生] where registration_no = +cast(@registration_no as varchar(11))" | findstr /v /c:"-" /b > "d:\student.csv"' @SMor 仍然得到:必须声明标量变量“@registration_no”。 【参考方案1】:
create procedure sp_CSV_Export
@regno int
as
Begin
Declare @registration_no int = @regno
declare @bcp varchar(8000)

set @bcp = 'sqlcmd -s, -W -Q "set nocount on; SELECT * FROM [Student_Management].[dbo].[Student] WHERE registration_no= '+ cast(@registration_no as nvarchar(10))+' " | findstr /v /c:"-" /b > "d:\student.csv"'    
EXEC master..xp_cmdshell @bcp
end

成功了!

【讨论】:

以上是关于在扩展存储过程-exec master..xp_cmdshell 中传递/使用标量变量的主要内容,如果未能解决你的问题,请参考以下文章

长存储过程在某些 exec 之后停止返回结果,为啥?

在存储过程中使用带有 exec @sql 的临时表

Oracle中执行存储过程call和exec区别

商业ERP都不用存储过程的吗

如何在不使用存储过程的情况下在表函数中返回值 exec?

SQL 001.02存储过程创建存储过程(create proc)带输出参数的存储过程执行存储过程(exec)