2011-03-10 28 views
2

我正在尝试制作一个使用sp_executesql的存储过程。我看了很久很难here,但我不明白我在我的代码中做了什么错误。我是通用的存储过程/ sql服务器函数的新手,所以我猜我缺少一些简单的东西。存储过程更改发生得很好,但是当我尝试运行它时,出现错误。使用带参数的sp_executesql抱怨需要声明一个变量

错误说。

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服务器实例以用于报告目的。当我有一个包含多个行的每个人id的表,每个表都包含一个值时,我经常需要他们在单个单元格中供用户使用。

回答

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

+0

关于“select * from @tablename”的部分描述了我为维护目的而要做的事情。我有从多值数据库导出的10s-100s字段。这些是从供应商产品中导出的,并放置在每行具有人员ID和值的表格中。为了报告的目的,代码通常被编写为将所有这些值合并为一。由于相同的代码正在被写入任何地方,我认为通过在一个地方编写这种反复出现的趋势可能会更容易维护。我是否应该把它吸起来,让同样的结构在任何地方重复? – wilbbe01

+0

@ wibbe01,阅读文章中的链接文章。动态SQL有它的位置,但如果使用不当,尤其像传递表名和列名一样危险。它非常容易发生SQL注入。在您的情况下使用一些代码生成工具生成SP可能会更安全。但是,如果您决定走这条路线,请特别小心。 –

3

你不能参数化的表名,所以用@atableName

您需要连接与atableName,哪一种失败的目的FO使用sp_executesql

第一位将失败
+0

感谢。我想我会以不同的方式做。我想在这里完成的完整查询时间比较长。你是否说在需要它的地方连接这个表名应该以与使用sp_executesql不同的方式完成?谢谢你的帮助。 – wilbbe01

+1

看到Andriy M的回答:但是这会让你打开SQL注入。就个人而言,我不会打扰,并在我的数据库中有几个对象 – gbn

2

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

而应该使用变量构造的动态查询。像这样:

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

参数被用来传递,典型地为在过滤器条件下使用。