如何在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。
使用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
秒部分都不会有问题。
感谢Marcin, 我收到错误:“ISNULL函数需要2个参数” – wotney 2013-03-27 11:46:16
@wotney更新了我的答案。请现在检查一下。 – MarcinJuraszek 2013-03-27 11:47:31
太棒了 - 非常感谢你! – wotney 2013-03-27 11:48:06
谢谢你,Remus。 是的 - 我从来没有真正使用*,但这是为了方便解释我的问题。 – wotney 2013-03-27 12:30:31