Consolidated:用于过滤的SQL Pass逗号分隔值

时间:2009-11-02 13:47:43

标签: sql sql-server filtering csv

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

我有一个'项目'表,我有一个搜索SP。我希望能够搜索多个ItemCodes,如:

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

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


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

  • 动态SQL可能是最不复杂的方式,但由于性能,安全性(SQL-Injection等)等参数,我不想考虑它。

还有其他方法,如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))

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

谢谢。

1 个答案:

答案 0 :(得分:0)

我认为在这种情况下使用动态T-SQL将是务实的。如果你对设计很谨慎,那么动态sql就像魅力一样。当它适合时,我已经在无数项目中利用它。有了这个说,让我解决你的两个主要问题 - 性能和SQL注入。

关于性能,请参阅参数化动态sql和sp_executesql(而不是sp_execute)的T-SQL参考。参数化sql和使用sp_executesql的组合将确保重用查询计划并避免sp_recompiles,从而使您在性能方面脱颖而出!我甚至在实时环境中使用了动态sql,它就像这两个项目的魅力一样。为了您的满意,您可以运行带有和不带两个优化的sp的大约百万次循环调用,并使用sql profiler来跟踪sp_recompile事件。

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

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

我希望这会有所帮助。 -Tabrez