【问题标题】:Consolidated: SQL Pass comma separated values in SP for filtering合并:SQL 在 SP 中传递逗号分隔值以进行过滤
【发布时间】:2010-12-12 07:08:21
【问题描述】:

我在这里分享对以下场景的综合分析:

我有一个“项目”表,并且我有一个搜索 SP。我希望能够搜索多个 ItemCode,例如:

- Table structure : Item(Id INT, ItemCode nvarchar(20))
- Filter query format: SELECT * FROM Item WHERE ItemCode IN ('xx','yy','zz')

我想使用存储过程动态地执行此操作。我将传递一个@ItemCodes 参数,该参数将具有逗号(',') 分隔值,并按上述方式执行搜索。


嗯,我已经访问了很多帖子\论坛,这里有一些主题:

  • 动态 SQL 可能是最简单的方式,但我不想考虑它,因为性能、安全性(SQL 注入等)等参数......

还有其他方法,如 XML 等。如果它们使事情变得复杂,我将无法使用它们。

最后,请不要使用额外的临时表 JOIN 类的性能技巧。 我必须管理性能和复杂性。

http://www.sommarskog.se/arrays-in-sql-2005.html 这将要求我在将参数类型传递给 SP 时“声明”参数类型,这会扭曲抽象(我没有在我的任何参数中设置类型,因为它们中的每一个都以通用方式处理)

http://www.sqlteam.com/article/sql-server-2008-table-valued-parameters 这是一种结构化方法,但它增加了复杂性,需要更改 DB 结构级别,并且不像上面那样抽象。

http://madprops.org/blog/splitting-text-into-words-in-sql-revisited/ 好吧,这似乎与我的旧解决方案相匹配。这是我过去所做的 -

I created an SQL function : [GetTableFromValues] (returns a temp table populated each item (one per row) from the comma separated @ItemCodes)

而且,这就是我在 SP 的 WHERE caluse 过滤器中使用它的方法 -

SELECT * FROM Item WHERE ItemCode in (SELECT * FROM[dbo].[GetTableFromValues](@ItemCodes))

这个是可重复使用的,看起来简单而简短(当然是相对而言的)。我错过的任何东西或任何有更好解决方案的专家(显然“在”上述几点的限制内)。

谢谢。

【问题讨论】:

  • 好吧,许多专家以及许多论坛帖子都建议我直接从应用程序中使用动态 T-SQL .. 与部署 SP 具有相同的好处!!!这使我的问题颠倒过来,我可以摆脱一个完整的动态 SQL 生成,并从我的应用程序代码中实际“创造奇迹”.. 这听起来是一个公平的想法吗?
  • 我知道你是从性能的角度来看这个的,但是在应用程序中保持动态查询构造的另一个很好的理由是在 SP 中使用 TSQL 执行它是丑陋的并且难以维护.如果你真的想使用 SP,我认为最好的方法是使用 GetTableFromValues UDF,因为这确实避免了在 SP 中编写动态 SQL。

标签: sql sql-server filtering csv


【解决方案1】:

我认为在这种情况下使用动态 T-SQL 将是实用的。如果你对设计很小心,动态 sql 就像一个魅力。当它合适时,我在无数项目中利用它。话虽如此,让我来解决您的两个主要问题 - 性能和 sql 注入。

关于性能,请阅读关于参数化动态 sql 和 sp_executesql(而不是 sp_execute)的 T-SQL 参考。参数化 sql 和使用 sp_executesql 的组合将确保重复使用查询计划并避免 sp_recompiles,从而使您摆脱性能困境!即使在实时上下文中我也使用过动态 sql,它就像处理这两个项目的魅力一样。为了您的满意,您可以在使用和不使用这两种优化的情况下对 sp 进行数百万次左右的循环调用,并使用 sql profiler 跟踪 sp_recompile 事件。

现在,关于 SQL 注入。如果您使用不正确的用户小部件(例如文本框)来允许用户输入商品代码,这将是一个问题。在这种情况下,黑客可能会编写选择语句并尝试提取有关您的系统的信息。您可以编写代码来防止这种情况,但我认为沿着这条路线走是一个陷阱。而是考虑使用适当的用户小部件,例如允许多选的列表框(取决于您的前端平台)。在这种情况下,用户只需从“提供的物品”列表中进行选择,您的代码将生成包含相应物品代码的字符串。基本上你不会将用户文本传递给动态 sql sp!您甚至可以使用基于 JQuery 的更流畅的选择小部件,但最重要的是,用户不会输入任何影响您的数据层的不可接受的文本。

接下来,您只需要在数据库上使用一个简单的存储过程,该过程接受项目代码的参数(例如,'''xyz'''、'''abc''')。在内部,它应该使用带有参数化动态查询的 sp_executesql。

我希望这会有所帮助。 -塔布雷兹

【讨论】:

  • 我同意如果谨慎使用 T-SQL 可以发挥很多作用。然而,回到我的场景,T-SQL 总是会面临 SQL 注入的威胁,应用程序开发人员必须确保他有一个安全的输入法。我希望我的方法能让开发者摆脱这种担忧,同时也为在过滤器中使用动态逗号分隔值提供了一种简洁明了的方法。
  • 正如我所提到的,如果您控制前端输入的获取方式,则使用 sp 路由可以避免 sql 注入。如果应用程序开发人员在另一个组中并且您无法控制数据收集,最好对 SQL 关键字进行简单检查,例如 SELECT、@ 符号(系统变量)和括号(以筛选函数调用)。我认为在大多数情况下,拥有一个参数化的存储过程将使您免受这些问题的影响,因为 SQL 参数是引号编码的。但是,如果有疑问,可以将上述检查放入一个函数中,以便在触发 sql 之前测试字符串。
  • 最好有功能,因为它在其他 SP 中也是全局的和有用的。并将逻辑/控制/更改限制在单个功能中。更好的进一步增强。谢谢。
猜你喜欢
  • 2021-01-11
  • 1970-01-01
  • 1970-01-01
  • 2011-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多