如何在SQL Server中传递可选的日期参数

问题描述:

我认为这应该很简单,但我仍然遇到问题。 我只想返回位于日期范围之间的表中的所有数据。但我希望日期范围是可选的。如何在SQL Server中传递可选的日期参数

ALTER PROCEDURE [dbo].[sp_ExistingPlacements_Get] 
    @DateFrom DATE = NULL, 
    @DateTo DATE = NULL 
AS 
BEGIN 
    SET NOCOUNT ON; 
    SELECT * 
    FROM tblExistingPlacements 
    WHERE 
     CreatedDT > COALESCE(NULLIF(@DateFrom, ''), @DateFrom) 
     AND 
     CreatedDT < COALESCE(NULLIF(@DateTo, GETDATE()), @DateTo) 
END 

所以,如果没有日期传入,我们返回整个表。

如果仅传递开始日期(DateFrom),则返回rows>开始日期和所有直到当前日期。

如果只有结束日期(dateTo)方法被传递,然后返回所有行<结束日期

当然,如果这两个日期都过去了,其间返回这些日期的所有行。

我是否与COALESCE走错了路线?

不要这样做。 SQL将不得不创建一个执行计划,在任何情况下工作。尽管听起来unituitive,最好是有三个独立的查询:

ALTER PROCEDURE [dbo].[sp_ExistingPlacements_Get] 
    @DateFrom DATE = NULL, 
    @DateTo DATE = NULL 
AS 
BEGIN 
    SET NOCOUNT ON; 
    IF (@DateFrom IS NULL and @DateTo IS NULL) 
     SELECT field, field, field 
     FROM tblExistingPlacements 
     WHERE CreatedDT < GETUTCDATE(); 
    ELSE IF (@DateFrom IS NULL) 
     SELECT field, field, field 
     FROM tblExistingPlacements 
     WHERE CreatedDT < @dateTo; 
    ELSE IF (@DateTo IS NULL) 
     SELECT field, field, field 
     FROM tblExistingPlacements 
     WHERE CreatedDT BETWEEN @DateFrom AND GETUTCDATE(); 
    ELSE 
     SELECT field, field, field 
     FROM tblExistingPlacements 
     WHERE CreatedDT BETWEEN @DateFrom AND @DateTo; 
END 

返回没有指定参数,当整个表的智慧是非常值得怀疑的,但是这不是重点。再说:

  • 从来没有在查询中使用*,始终指定投影列表中明确
  • 总是使用UTC时间在数据库中

有关此主题的深入讨论见Dynamic Search Conditions in T-SQL

+0

谢谢你,Remus。 是的 - 我从来没有真正使用*,但这是为了方便解释我的问题。 – wotney 2013-03-27 12:30:31

使用ISNULL(@parameter) OR (--your condition--)而不是COALESCE

BEGIN 
    SET NOCOUNT ON; 
    SELECT * 
    FROM tblExistingPlacements 
    WHERE 
     ((@DateFrom IS NULL) OR CreatedDT > @DateFrom) 
     AND 
     ((@DateTo IS NULL) OR CreatedDT < @DateTo) 
END 

如果参数未提供ISNULL回报TRUE,所以OR秒部分都不会有问题。

+0

感谢Marcin, 我收到错误:“ISNULL函数需要2个参数” – wotney 2013-03-27 11:46:16

+0

@wotney更新了我的答案。请现在检查一下。 – MarcinJuraszek 2013-03-27 11:47:31

+0

太棒了 - 非常感谢你! – wotney 2013-03-27 11:48:06