我在这里分享以下情景的综合分析:
我有一个'项目'表,我有一个搜索SP。我希望能够搜索多个ItemCodes,如:
- Table structure : Item(Id INT, ItemCode nvarchar(20))
- Filter query format: SELECT * FROM Item WHERE ItemCode IN ('xx','yy','zz')
我想使用存储过程动态执行此操作。我将传递一个@ItemCodes参数,该参数将包含逗号(',')分隔值,并且搜索shud将按上述方式执行。
好吧,我已经访问了很多帖子\论坛,这里有一些话题:
还有其他方法,如XML等。如果它们使事情变得复杂,我就无法使用它们。
最后,没有额外的临时表JOIN那种性能打击技巧。 我要管理性能和复杂性。
Passing an "in" list via stored procedure 我已经回顾了上面两篇文章,并提供了一些解决方案,这里有一些限制:
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))
这个是可重复使用的,看起来简单而简短(当然相对而言)。任何我错过的东西或任何有更好解决方案的专家(显然“在上述要点的限制范围内”)。
谢谢。
答案 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