【问题标题】:dynamic filters and sp_executesql动态过滤器和 sp_executesql
【发布时间】:2015-06-03 18:30:35
【问题描述】:

我有一个存储过程,它有一个参数@SomeFilterIds,它接受逗号分隔的整数 id。如果此参数不为 NULL,则将其转换为如下内容:

AND [X] IN(1, 2, 4) 

并分配给@SomeFilter

然后我按照这些思路使用了一些东西:

SET @Sql = N' ...WHERE    
 c.SomeDate >= @SomeDate
' + @SomeFilter

和:

SET @ParameterDefinition = N'@SomeDate DateTime';
EXEC sp_executesql 
@Sql
,@ParameterDefinition
,@SomeDate = @SomeDate

我认为这不是最佳做法,并且会打开潜在的安全漏洞。这个对吗?这可以改进吗?谢谢。

【问题讨论】:

  • 你真的需要动态sql吗?如果传递逗号分隔的值字符串是唯一的原因,那么还有更好的方法,例如使用表值参数。
  • 我也因为其他原因需要它。
  • 好的,但是您真的需要它吗?动态 sql 应该是最后的手段,因为它既危险又慢。如果您可以分享相关详细信息,也许有人可以向您展示避免这种情况的方法。
  • Zohar 请善待并提供替代方案(答案)。强要求 sproc 接收 @SomeDate (DataTime) 和逗号分隔的整数 Id 列表(参见示例)。
  • Read this 了解如何从 c# 将表值参数传递给存储过程,但如果不知道您实际需要做什么以及正在执行什么代码,我无法给您准确的答案存储过程。

标签: sql-server tsql


【解决方案1】:

我认为您可以使用XML 类型变量代替@SomeFilterIds 作为varchar 参数,然后使用内部连接您的主表和这个XML 变量。 这将避免动态查询执行,并且会更安全。

例子:

--Instead of comma separated ID use below XML
declare @xml xml = '<row><ID>1</ID></row><row><ID>3</ID></row>'

--Assume this is your other table
declare @YourTable table (ItemId int, ColA varchar(20))

insert @YourTable
select 1, 'Hello World'


--Joining both the tables

select  col.value('data(ID[1])', 'int') as ID
from    @xml.nodes('/row') tbl(col) 
inner join @YourTable t2 
on t2. ItemId=tbl.col.value('data(ID[1])', 'int')
--WHERE  c.SomeDate >= @SomeDate 

【讨论】:

  • 你能举个例子吗?
  • 感谢您的更新。我真的不明白这与我的问题和 sp_executesql 有什么关系。也请不要让我在哪里进行过滤。
  • 基本上我建议您避免动态查询。我假设您使用 sp_executesql 是因为逗号分隔的 ID 列表。因此通过在 XML 中使用 ID 可以避免动态查询。如果你看到我的例子,我也提到了 where 条件,但它被评论了。那是你可以写其他条件的地方。
猜你喜欢
  • 1970-01-01
  • 2016-09-17
  • 2014-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-30
相关资源
最近更新 更多