使用带有params的sp_executesql会抱怨需要声明一个变量

时间:2011-03-10 19:35:59

标签: sql-server sql-server-2005 stored-procedures

我正在尝试创建一个使用sp_executesql的存储过程。我看起来很长很难here,但我无法在代码中看到我做错了什么。我一般都是存储过程/ sql服务器函数的新手,所以我猜我错过了一些简单的东西。存储过程更改很好,但是当我尝试运行它时,我收到错误。

错误说。

Msg 1087, Level 15, State 2, Line 3
Must declare the table variable "@atableName"

程序看起来像这样。

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go

ALTER PROCEDURE [dbo].[sp_TEST]
    @tableName varchar(50),
    @tableIDField varchar(50),
    @tableValueField varchar(50)
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @SQLString nvarchar(500);
    SET @SQLString = N'SELECT DISTINCT @aTableIDField FROM @atableName';
    EXEC sp_executesql @SQLString,
            N'@atableName varchar(50),
              @atableIDField varchar(50),
              @atableValueField varchar(50)',
            @atableName = @tableName,
            @atableIDField = @tableIDField,
            @atableValueField = @tableValueField;
END

我试图用这样的东西来称呼它。

EXECUTE sp_TEST 'PERSON', 'PERSON.ID', 'PERSON.VALUE'

此示例不添加任何特殊内容,但我有大量具有类似代码的视图。如果我可以使这个存储过程正常工作,我可以大量缩减重复代码。

感谢您的帮助。

编辑:为了便于维护,我尝试这样做。我有多个视图,基本上具有相同的确切sql,除了表名不同。将数据带到SQL Server实例以进行报告。当我有一个包含每人id多行的表,每个包含一个值时,我经常需要在单个单元格中为用户提供这些行。

3 个答案:

答案 0 :(得分:3)

您无法对表名进行参数化,因此它将失败并显示@atableName

你需要将第一位与atableName连接起来,这种方式与使用sp_executesql的目的相悖

答案 1 :(得分:3)

除非你只是想学习和试验,否则这样做是不可行的。

ALTER PROCEDURE [dbo].[sp_TEST]
    @tableName varchar(50),
    @tableIDField varchar(50),
    @tableValueField varchar(50)
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @SQLString nvarchar(500);
    SET @SQLString = N'SELECT DISTINCT ' + quotename(@TableIDField) + ' FROM ' + quotename(@tableName);
    EXEC sp_executesql @SQLString;
END

阅读The Curse and Blessings of Dynamic SQL

答案 2 :(得分:2)

您不能使用变量将表名和列名作为参数传递给动态查询。如果可能的话,我们实际上不会使用动态查询!

相反,您应该使用变量构造动态查询。像这样:

SET @SQLString = N'SELECT DISTINCT ' + QUOTENAME(@TableIDField) +
                  ' FROM ' + QUOTENAME(@TableName);

参数用于传递,通常用于过滤条件。