我认为这应该很简单,但我一直遇到问题。 我只想从位于日期范围之间的表中返回所有数据。但我希望日期范围是可选的。
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走错了路线?
答案 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
当没有指定参数时返回整个表的智慧是非常值得怀疑的,但这不是重点。除了:
*
,始终明确指定投影列表有关此主题的详尽讨论,请参阅Dynamic Search Conditions in T-SQL。