在SQL查询中实现可选参数是不好的做法吗?

时间:2016-06-08 15:43:10

标签: sql-server tsql

考虑以下在AdventureWorks2014数据库上运行的查询:

DECLARE @OrderID int=43659, @ProdID int =-1;

SELECT * FROM Sales.SalesOrderDetail sod
WHERE sod.SalesOrderID = @OrderID
  AND sod.ProductID = CASE WHEN @ProdID = -1 THEN sod.ProductID ELSE @ProdID END

@ProdID用作可选参数。有时我对订单中的所有商品和其他时间感兴趣 - 仅限具有特定ProductID的商品。以AND开头的WHERE子句的一部分用于此目的。

如果将-1作为@ProdID的值传递,则WHERE的这部分基本上被忽略。

如果我将771作为@ProdID的值传递,我将只收到ProductID = 771的项目。

此查询从ASP.Net C#应用程序的代码隐藏传递到SQL Server。所以在这种特殊情况下,我可以动态构建查询,如果C#中的ProdID参数为-1,我可以完全省略从AND开始的部分查询,而不是将ProdID的值传递给SQL。但是,按照上述方式进行操作会使开发和调试变得更容易(如果我想将此代码放在存储过程中,以后这是唯一的方法)。

这是一种不好的做法吗?或者SQL Server“足够智能”忽略WHERE子句中的“sod.ProductID = sod.ProductID”部分,它对性能没有影响吗?

3 个答案:

答案 0 :(得分:3)

让程序逻辑选择适当的查询,否则您可能会冒险改变有效的“搜索”问题。利用索引进入扫描

IF @ProdID = -1 THEN
    SELECT * FROM Sales.SalesOrderDetail sod
    WHERE sod.SalesOrderID = @OrderID

ELSE
    SELECT * FROM Sales.SalesOrderDetail sod
    WHERE sod.SalesOrderID = @OrderID
    AND sod.ProductID = @ProdID;

答案 1 :(得分:1)

DECLARE @OrderID int=43659, @ProdID int =-1;

SELECT * FROM Sales.SalesOrderDetail sod
WHERE sod.SalesOrderID = @OrderID
  AND (@ProdID = -1 or sod.ProductID = @ProdID) 

或传递null @ProdID以获取所有内容 这可能比或

更快
 AND isnull(@ProdID, sod.ProductID) = sod.ProductID

答案 2 :(得分:0)

是的,这是一种不好的做法。

我为回答我自己的问题而道歉,但我刚刚在MSDN上收到了一些很好的答案,这些答案非常详细地介绍了这个主题,所以真正归功于他们(或者更确切地说是那些撰写他们推荐给我的文章的人): / p>

https://social.msdn.microsoft.com/Forums/sqlserver/en-US/12e2e169-987b-4df9-8696-44697aba15aa/is-this-a-bad-practice-to-implement-optional-parameters-in-sql-query?forum=transactsql

MSDN发布的文章:

http://www.sqlskills.com/blogs/kimberly/high-performance-procedures/

http://www.sommarskog.se/dyn-search-2008.html

http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/(这个也使用AW数据库作为例子)