sql存储过程参数作为动态查询的参数

时间:2012-07-26 12:31:05

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

此过程有三个参数。但是当我尝试通过传递参数执行时它会向我显示错误。请帮帮我。

create procedure queryfunctions @Tabname varchar(150),@colname varchar(150),@valuesname varchar(150)
as
begin
declare @sql varchar(4000)
select @sql='select * from @Tabname where @colname=@valuesname'
exec(@sql)
end

exec queryfunctions 'education','eduChildName','Revathi'

错误:

  

Msg 1087,Level 15,State 2,Line 1           必须声明表变量“@Tabname”。

2 个答案:

答案 0 :(得分:12)

这是一个更安全的选择:

ALTER PROCEDURE dbo.queryfunctions 
  @Tabname NVARCHAR(511),
  @colname NVARCHAR(128),
  @valuesname VARCHAR(150)
AS
BEGIN
  SET NOCOUNT ON;

  DECLARE @sql NVARCHAR(MAX);

  SET @sql = 'SELECT * FROM ' + @Tabname 
           + ' WHERE ' + QUOTENAME(@colname) + ' = @v';

  EXEC sp_executesql @sql, N'@v VARCHAR(150)', @valuesname;
END
GO

EXEC dbo.queryfunctions N'dbo.education', N'eduChildName', 'Revathi';

我改变了什么?

  1. 创建/引用对象时始终使用dbo前缀。
  2. 表格和列名称为NVARCHAR 超过150个字符。允许参数容纳某人可能在将来添加的表格更安全。
  3. 添加SET NOCOUNT ON作为防范网络开销并可能向客户端发送错误的结果集。
  4. @sql应始终为NVARCHAR
  5. 围绕实体名称(如表或列)使用QUOTENAME来帮助阻止SQL注入,并防止选择不当的名称(例如关键字)。
  6. 尽可能使用适当的参数(再次帮助阻止SQL注入,同时避免在字符串参数上进行各种分隔符转义)。

答案 1 :(得分:-3)

为什么要将对象名称作为参数传递?

如果将字符串值传递给@valuesname,则代码应为

create procedure queryfunctions 
(
@Tabname varchar(150),@colname varchar(150),@valuesname varchar(150) 
)
as 
begin 
declare @sql varchar(4000) 
select @sql='select * from '+@Tabname+' where '+@colname+'='''+@valuesname+'''' 
exec(@sql) 
end 

不知道如何在动态sql中使用单引号?请参阅此http://beyondrelational.com/modules/2/blogs/70/posts/10827/understanding-single-quotes.aspx