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

时间:2013-03-27 11:40:29

标签: sql-server stored-procedures

我认为这应该很简单,但我一直遇到问题。 我只想从位于日期范围之间的表中返回所有数据。但我希望日期范围是可选的。

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),我们返回行&gt;开始日期和所有截至当前日期。

如果仅传递结束日期(DateTo),则返回所有行&lt;结束日期

当然,如果两个日期都通过,则返回这些日期之间的所有行。

我是否使用COALESCE走错了路线?

2 个答案:

答案 0 :(得分:7)

使用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的第二部分无关紧要。

答案 1 :(得分:3)

不要这样做。 SQL必须创建一个执行计划,该计划适用于任何情况。尽管听起来比较单一,但最好有三个单独的查询:

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