Use sp_executesql to run xp_cmdshell with variable

有些话、适合烂在心里 提交于 2019-12-11 11:01:58

问题


Trying to run xp_cmdshell with sp_executesql without success, database is SQL Server 2008R2

Here is the SQL

DECLARE @sql nvarchar(max) = N'EXEC xp_cmdshell ''BCP "SELECT data FROM TableA WHERE id = @id" queryout C:\Temp\test.dat -T -N'''
EXEC sp_executesql @sql, N'@id numeric(19, 0)', @id = 1234

The error is

Error = [Microsoft][SQL Server Native Client 10.0][SQL Server]Must declare the scalar variable "@id".

Please help, thank you!


回答1:


The error is due to the @id variable reference in your @sql string being in an escaped-sub-string (i.e. the BCP string being executed by xp_cmdshell). So you could just escape out of that sub-string.

DECLARE @id NUMERIC(19, 0)
DECLARE @sql NVARCHAR(MAX)

SET @id = 1234
SET @SQL = N'DECLARE @BCP NVARCHAR(4000); 
SET @BCP = ''BCP "SELECT data FROM TableA WHERE id = ''
           + CONVERT(NVARCHAR(30), @id) + N''" queryout C:\Temp\test.dat -T -N'';
PRINT @BCP
EXEC xp_cmdshell @BCP;
'

EXEC sp_executesql @sql, N'@id NUMERIC(19, 0)', @id = 1234

But that is still more effort than is needed here. Just concatenate the @id value into the string and then use EXEC(). There is no need to use sp_executesql as you don't need the performance benefit of caching the query plan.

DECLARE @id NUMERIC(19, 0)
DECLARE @sql NVARCHAR(MAX)
SET @id = 1234
SET @SQL = N'EXEC xp_cmdshell ''BCP "SELECT data FROM TableA WHERE id = '  
           + CONVERT(NVARCHAR(30), @id) + N'" queryout C:\Temp\test.dat -T -N'''

PRINT @SQL
EXEC(@SQL)



回答2:


The problem is that the variable @id doesn't exist in the scope of the procedure xp_cmdshell. In other words, @id is not being replaced with the actual value in the string SELECT data FROM TableA WHERE id = @id. Better replace the variable called @id and then execute your query.

SET @sql = REPLACE(@sql,'@id',@id);

Your code updated:

DECLARE @id NUMERIC(19, 0)
SET @id = 3087

DECLARE @sql nvarchar(max) = N'EXEC xp_cmdshell ''BCP "SELECT data FROM TableA WHERE id = @id" queryout "C:\Temp\test.dat" -T -N '''
SET @sql = REPLACE(@sql,'@id',@id);
EXEC sp_executesql @sql


来源:https://stackoverflow.com/questions/22777561/use-sp-executesql-to-run-xp-cmdshell-with-variable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!