考虑以下在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”部分,它对性能没有影响吗?
答案 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>
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数据库作为例子)