【问题标题】:Adding to WHERE clause conditions using CASE使用 CASE 添加到 WHERE 子句条件
【发布时间】:2017-06-15 02:46:05
【问题描述】:

我有一个接受可选@ID 参数的存储过程。当参数传入时,我希望 WHERE 语句包含类似 id = @ID 的内容,否则,当 @ID 为空时,我不希望它被过滤。

例如:

@ID BIGINT = NULL

SELECT * from myTable
WHERE 
CASE
    WHEN @ID IS NOT NULL THEN mytable.id = @ID
END

我在 SQL Server 2016 中运行它,它在 mytable.id = @ID 附近显示错误的语法。可以以这种方式使用 CASE 还是应该为此尝试不同的 SQL 方法?

我认为实现此目的的唯一其他选择是在我的存储过程中使用 IF 条件,但根据我的搜索,这似乎也不可能。

【问题讨论】:

  • 你能把你的查询改成@ID BIGINT = NULL SELECT * from myTable WHERE @ ID IS NULL or mytable.id = @ ID

标签: sql sql-server case


【解决方案1】:

CASE 是一个表达式,而不是一个语句。它不是用来控制这样的流量的,它不会起作用。

你的逻辑应该是这样的。

Where mytable.id = ISNULL(@ID, mytable.id)

我应该提醒您,这种模式可能会导致性能不佳。有关更详细的说明和其他一些选项,您应该查看这篇文章。 http://www.sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/

【讨论】:

  • 我将标记为正确,因为这是与我的问题最接近的直接回答它的答案。更有效的解决方案需要大量的返工。
  • 实际上,如果这是一个存储过程,您可以简单地使用 RECOMPILE 提示(只要编译该过程不是什么大问题),您应该继续获得非常好的执行计划。 Gail 在我链接的她的文章中讨论了这一点。
【解决方案2】:

表现不佳的方法是:

WHERE ISNULL(@ID,mytable.id) = mytable.id

性能更好的方法是:

 if(@ID IS NULL)
   select * from ... without the WHERE condition
else
    do your query with the condition mytable.id = @ID

或者在存储过程中动态构建查询,通过sp_executesql传参执行

注意:如果表格足够小,请坚持简单并使用第一个选项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 2013-12-23
    • 2021-04-09
    相关资源
    最近更新 更多