排序、排序、筛选 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,但这很快就会变成一棵巨大的树,维护起来将是一场噩梦。

我不是第一个需要这样的解决方案的人,一定有比上述更好的方法吗?另外一个附带问题是,除了做很多IFs 之外,还有一个好方法可以以参数化的方式按方向排序吗?

【问题讨论】:

如果您可以将过滤器减少到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 的复杂组合的主要内容,如果未能解决你的问题,请参考以下文章

第89天:NumPy 排序和筛选函数

excel如何对数据进行多字段同时排序多条件组合和多条件筛选呢

数据库中复杂的联查+筛选条件+排序+分页

SQL server中的物理排序和逻辑排序是怎么回事

SQL中表中字段筛选后排序,然后进行排名。 在线等!!!

SQL Server基础:拾遗