【问题标题】:Remove the where clause when the value supplied is null当提供的值为 null 时删除 where 子句
【发布时间】:2018-10-27 19:02:59
【问题描述】:

我想根据提供的值自动附加 where 子句

让我们考虑一个包含选择查询的存储过程

CREATE PROCEDURE [dbo].[example]
    @From DATETIME,
    @T0 DATETIME
AS
  BEGIN TRY
      SELECT * 
      FROM footable 
      WHERE Fromdate = @From AND Todate = @TO
 END TRY

如果@From 的值为null,那么where 子句必须是

SELECT * 
FROM footable 
WHERE Todate = @TO

有什么方法可以实现吗?

非常感谢您的回答。但这也不能解决我的问题,因为@From@To 都是可选的。按照这种方法,我的代码会喜欢

SELECT * 
FROM footable 
WHERE (Fromdate = @From OR @From IS NULL)
  AND (Todate = @TO OR @To IS NULL)

执行此操作会导致整个表。

【问题讨论】:

  • Andrew 的解决方案是解决这个问题的好方法。但请注意,您可能会遇到性能问题,尤其是随着数量或参数的增加。 Gail Shaw 在这里有一篇关于这类事情的精彩文章。 sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries
  • 我不确定您提出的问题是否正确,您似乎想过滤介于日期参数之间的数据,而这不会因为您匹配日期@from = fromdate。如果我错了,请道歉
  • @Tanner - 我认为你是对的,但鉴于它来自footable,我不确定代码是否代表正确的程序,但只是为了解决问题。参数@T0 之后是@TO(从零到O)
  • @Tanner :你是绝对正确的。这不是我试图编写的确切代码。但只是为了这个问题。@Andrew:完全正确,先生

标签: sql sql-server


【解决方案1】:

用正常的逻辑来处理就行了。

SELECT * 
FROM footable 
WHERE (Fromdate = @From or @From is null)
AND Todate = @TO
option (OPTIMIZE FOR (@From UNKNOWN))

编辑:在其中添加了option 子句,以便查询计划针对未知值进行优化,并且不受参数嗅探的影响,从而在缓存中创建初始计划。或者,如果使用情况已知,您可以使用生成所需计划的已知值。

我会先选择这个选项,然后再沿着option (recompile) 的路线前进 - 这需要每次都生成计划。

【讨论】:

  • 这肯定行得通,但很可能会出现性能问题。如果您使用 NOT NULL 参数集运行此存储过程,那么它将生成也将用于 NULL 的计划。
  • 是的,这种查询的稳定计划是有问题的 - 它是一个有效的调用,我将添加选项以限制它
  • 喜欢OPTIMIZE FOR 的建议。
猜你喜欢
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
  • 2021-09-19
相关资源
最近更新 更多