必须声明标量变量“@TEMPLATE_NAME”

时间:2013-07-16 10:24:49

标签: sql-server-2008 tsql

我在尝试执行以下代码时遇到错误,寻找类似的解决方案,但无法弄清楚。

DECLARE @TAB_COL_NAME TABLE(idx int identity(1,1), COLUMNNAME VARCHAR(MAX))
DECLARE @TEMPLATE_NAME NVARCHAR(50)
SET @TEMPLATE_NAME = 'MYTABLE1'
INSERT INTO @TAB_COL_NAME EXEC('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '+@TEMPLATE_NAME)

由于我看到很多人说使用sp_executesql,,我尝试了sp_executesql

  DECLARE @SQL NVARCHAR(100)
  DECLARE @TEMPLATE_NAM NVARCHAR(50)
  SET @TEMPLATE_NAM = 'MYTABLE1'
  SET @SQL = N'SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '+ '@TEMPLATE_NAME'
 EXEC sp_executesql @SQL,
                   '@TEMPLATE_NAME Nvarchar(50)',
                    @TEMPLATE_NAME = @TEMPLATE_NAM

这会发出错误:Procedure expects parameter '@parameters' of type 'ntext/nchar/nvarchar'.

对此有什么正确的解决方案?

我无法实现这一目标在EXEC SQL

一些回复会有所帮助。

3 个答案:

答案 0 :(得分:2)

为什么要尝试传递变量?在您的情况下,您不一定要这样做。使用串联尝试以下操作:

DECLARE @SQL NVARCHAR(100)
  DECLARE @TEMPLATE_NAME NVARCHAR(50)
  SET @TEMPLATE_NAME = 'mytable'
  SET @SQL = N'SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '''+ @TEMPLATE_NAME + ''''
  print @SQL
 EXEC sp_executesql @SQL

但是,如果必须参数化,则可以按以下方式使用sp_executesql

 DECLARE @SQL NVARCHAR(100)
  DECLARE @TEMPLATE_NAME NVARCHAR(50)
  SET @TEMPLATE_NAME = 'mytable';
  SET @SQL = N'SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @TEMPLATE_NAME';
 EXEC sp_executesql @SQL , N'@TEMPLATE_NAME NVARCHAR(50)',  @TEMPLATE_NAME

答案 1 :(得分:1)

将N添加到sp_executesql的第二个参数以生成常量nvarchar

EXEC sp_executesql @SQL,
               N'@TEMPLATE_NAME Nvarchar(50)',
                @TEMPLATE_NAME = @TEMPLATE_NAM

答案 2 :(得分:1)

虽然在给定的示例中不会发生,但用于通过连接字符串来执行sp_executesql的方法会受到sql注入的影响。这个答案正确使用参数。参数2定义了传递给字符串的参数,3 +是您传递的参数。

此外,如果您的参数中包含撇号,那么它将使连接版本失败:SET @TEMPLATE_NAME = '[MYTABLE''1]';。在这种情况下不太现实,但通常需要注意动态sql。

 DECLARE @SQL NVARCHAR(100);
  DECLARE @TEMPLATE_NAME NVARCHAR(50);
  SET @TEMPLATE_NAME = 'MYTABLE1';
  SET @SQL = N'SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @TEMPLATE_NAME';
 EXEC sp_executesql @SQL , N'@TEMPLATE_NAME NVARCHAR(50)',  @TEMPLATE_NAME;

Blog: Dynamic SQL & SQL injection