-1

名为 Emp 的表包含id,name,lname,birthdate,address and salery。我想从 emp 中进行选择。基本查询:select * from emp 如果传递 lname 的值,查询:select * from emp where lname = 'fgfg'像这样。所以我创建了以下 sp。

create Procedure Proc_selectEmp
(
@name varchar(10) = null,
@lname varchar(10) = null,
@id varchar(10) = null

)
as
begin

select * from Emp
where 
(@name is null or name = @name) 
and (@lname is null or lname = @lname) 
and (@id is null or id = @id)
end

与 emp 一样,有 13 个表具有相同的列名。所以我的tablenmae也是动态的。这就是为什么,我选择执行sp_executesql。我可以这样创建吗

create Procedure Proc_selectEmp
(
@name varchar(10) = null,
@lname varchar(10) = null,
@id varchar(10) = null
@tableName varchar(30)
)
as
begin
declare @query nvarchar(1000) 
set @query = @query +'select * from '+@tableName+'
where ('+@name+' is null or name = '+@name+') 
and ('+@lname+' is null or lname = '+@lname+') 
and ('+@id+' is null or id = '+@id+')
end'

execute sp_executesql @query
4

2 回答 2

1

它会起作用,虽然很臭,因为它要求它要求表名是一个变量,因此表必须具有相同的列定义。

此外,与其包含@param is null or column = @param,不如完全省略不必要的过滤器,这很容易做到,因为您使用的是动态 sql。这将避免参数嗅探问题

最后,不要将列过滤器附加到字符串中,而是使用 的参数化重载sp_executesql,这将保护您免受 SQL 注入攻击,并为您处理引号等的转义。不幸的是,@tablename 不能被参数化,但希望?这不是用户或外国提供的变量(在这种情况下,您需要对设计和/或验证技术进行更多思考)。

IE

declare @query nvarchar(max) 
set @query = N'select * from ' + @tableName + N` where (1=1)`

if (@name is not null)
  set @query = @query + N'and name = @name'

-- ... same for @id and @lname

exec sp_executesql @SQL, 
     N'@name varchar(10),
       @lname varchar(10),
       @id varchar(10)',
       @name = @name,
       @lname = @lname,
       @id = @id

编辑 回复:un-parameterizable在动态 sql 中保护表或列名之类的输入-有关想法,请参见此处的这篇文章-使用 QUOTENAME和将列/表名列入白名单非常突出。

于 2012-09-04T08:14:57.367 回答
-4

是的,你可以,但你必须写

EXECUTE(@query)    

代替

execute sp_executesql @query
于 2012-09-04T08:13:19.707 回答