排序、排序、筛选 SQL Server 的复杂组合
Posted
技术标签:
【中文标题】排序、排序、筛选 SQL Server 的复杂组合【英文标题】:Complex mix of sorting, ordering, filtering SQL Server 【发布时间】:2012-06-16 08:32:33 【问题描述】:基本上我必须从 SQL 数据库构建项目列表,但是用户可以选择对 7 个过滤器的任意组合进行过滤,也可以选择要排序的列以及按方向排序。
正如您可以想象的那样,这会以大量不同的组合进行编码,并且数据集非常大,所以我想避免在应用程序中这样做。
到目前为止,在我的存储过程中我已经尝试过:
构建查询字符串,虽然这非常简单易懂,但它会使应用程序容易受到 SQL 注入,因此我宁愿避免这种情况。
使用一组 IF ELSE
语句来运行正确的参数化 SQL,但这很快就会变成一棵巨大的树,维护起来将是一场噩梦。
我不是第一个需要这样的解决方案的人,一定有比上述更好的方法吗?另外一个附带问题是,除了做很多IF
s 之外,还有一个好方法可以以参数化的方式按方向排序吗?
【问题讨论】:
如果您可以将过滤器减少到and (fld1 = @filter1 or @filter1 is null)
,您应该阅读此sommarskog.se/dyn-search-2008.html
【参考方案1】:
构建一个查询字符串,虽然这非常简单易行 跟随,它使应用程序对 SQL 注入开放,所以我会 而是避免这种情况。
如果您使用 sp_executesql 并将您的参数作为参数传递给该存储过程,则不会。由于您将数据作为参数提供,因此不会有 sql 注入
http://sqlinthewild.co.za/index.php/2009/04/03/dynamic-sql-and-sql-injection/
http://blogs.msdn.com/b/raulga/archive/2007/01/04/dynamic-sql-sql-injection.aspx
我也尝试过使用一组 IF ELSE 语句来正常运行 参数化的 SQL 但是这很快就会变成一棵巨大的树,并将 一场噩梦。
如果您使用 IF ELSE 则表示同意,但还有一种称为 catch all queries
的模式WHERE (ProductID = @Product Or @Product IS NULL)
AND (ReferenceOrderID = @OrderID OR @OrderID Is NULL)
...
更多信息在这里http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/
请务必在末尾指定 OPTION (RECOMPILE),否则您的查询可能会因所谓的参数嗅探
而受到影响Also as a side question is there a good way to do order by and order by direction in a parameterised way, besides doing lots of IFs?
Dynamic Sorting within SQL Stored Procedures 可能重复
最后,您可以使用 sp_executesql 或捕获所有查询(这是这两种尝试过的解决方案的常见问题)。我通常更喜欢捕获所有查询,但不要忘记指定选项(重新编译)。
【讨论】:
您不能将where
子句作为参数传递给sp_executesql
。如果你动态构建sp_executesql
的SQL参数,那当然是对SQL注入开放的。,
@Andomar 我澄清了你必须将它们作为参数传递给存储过程的答案。我只想重新编译一个 catch all + 选项,这也将简化动态排序【参考方案2】:
对于过滤,使用COELSCE
按任意条件组合进行过滤。在您的存储过程中会有一个用户将搜索的所有参数的列表,然后在您的查询中将类似于:
SELECT *
FROM YourTable t
WHERE 1 = 1
AND t.FirstColumn = COALESCE(@FirstColumnParam, t.FirstColumn)
AND t.SecodndColumn = COALESCE(@SecondColumnParam, t.SecondColumn)
....
如果任何参数为空,则跳过条件。对于1=1
,如果没有过滤器代码传递给您的查询。
对于排序:您可以使用CASE
语句按任何选择的列排序:
ORDER BY ( CASE WHEN @OrderByParam = 1 Then FirstColumn ELSE .... END)
【讨论】:
如果你使用 COALESCE 函数,优化器会看到这是一个 SARG 并使用索引吗? @buckley,不,我认为它会创建索引以防万一它是按照你写的方式写的AND (FirstColumn = @FirstColumnParam OR @FirstColumnParam Is NULL)
@MahmoudGamal 非常感谢,工作愉快!有这么多漂亮的 SQL 关键字,我不时会像这样发现!
COALESCE 模式对于可空列将失败,因为 NULL 不等于 NULL。此外,在某些情况下,ISNULL 的性能比 COALESCE 好得多,尽管它们看起来相当。以上是关于排序、排序、筛选 SQL Server 的复杂组合的主要内容,如果未能解决你的问题,请参考以下文章