【问题标题】:Stored procedure with nullable value in date field日期字段中具有可为空值的存储过程
【发布时间】:2013-05-22 06:56:46
【问题描述】:

在这个存储过程中,在 where 条件下,如果 @startDate 和 @EndDate 值为 null,那么如何使用 COALESCE 处理它。

CREATE PROCEDURE  dbo.SP_ManageLeaveSearch

  @StartDate datetime,
  @EndDate datetime,

  @UserName CHAR(100), 
  @MarketID INT 

AS
BEGIN
    SELECT d1.UserName,c1.HouseName,c.StartDate,c.EndDate
        FROM  table1   c    
        Inner  JOIN table2  d1 ON c.UserID = d1.UserID


WHERE 
     (

        (
            (@StartDate BETWEEN StartDate AND EndDate)
            OR 
            (@EndDate BETWEEN StartDate AND EndDate) 
            OR
                (
                (@StartDate <= Startdate AND @EndDate>=EndDate)
                )
        )  
        AND
        (

             d1.UserName = COALESCE(@UserName, d1.UserName) 
        ) 

)

 END

提前问好。

【问题讨论】:

标签: c# asp.net sql-server stored-procedures


【解决方案1】:

这应该适合你:

CREATE PROCEDURE  dbo.ManageLeaveSearch

  @StartDate datetime = NULL,
  @EndDate datetime = NULL,

  @UserName CHAR(100) = NULL, 
  @MarketID INT 

AS
BEGIN
    SELECT d1.UserName,c1.HouseName,c.StartDate,c.EndDate
        FROM  table1   c    
        Inner  JOIN table2  d1 ON c.UserID = d1.UserID


WHERE 
     COALESCE(@StartDate,StartDate) <= EndDate AND
     StartDate <= COALESCE(@EndDate,EndDate) AND
     d1.UserName = COALESCE(@UserName, d1.UserName) 

 END

注意事项:

  • 不要使用 sp_ 前缀命名存储过程 - 它是为 Microsoft 的 system procedures 保留的。
  • 我使用了更简单的条件来确定是否存在重叠。如果范围 1 在范围 2 结束之前开始,并且范围 2 在范围 1 结束之前开始,则两个范围之间存在重叠。
  • 我已经为那些应该可以为空的参数指定了默认值。

【讨论】:

  • 在这种情况下没有得到开始日期和结束日期是同一天的记录。
  • @Ashok - 这只是将&lt; 更改为&lt;=,我现在已经完成了。您并没有真正定义您的输入,我也没有仔细考虑原始查询中的边缘条件。很容易调整(通过决定使用&lt;&lt;=)您希望范围的端点是包容性的还是独占性的。通常,如果还有时间组件,您可能希望 @endDate/EndDate 是独占的,而不是包含的。
【解决方案2】:

试试这个 -

CREATE PROCEDURE dbo.usp_ManageLeaveSearch

  @StartDate DATETIME,
  @EndDate DATETIME,

  @UserName CHAR(100), 
  @MarketID INT 

AS BEGIN

    SELECT 
          d1.UserName
        , c.HouseName
        , c.StartDate
        , c.EndDate
    FROM dbo.table1 c    
    JOIN dbo.table2 d1 ON c.UserID = d1.UserID
    WHERE d1.UserName = ISNULL(@UserName, d1.UserName) 
        AND (
              ISNULL(@StartDate, StartDate) BETWEEN StartDate AND EndDate
            OR 
              ISNULL(@EndDate, EndDate) BETWEEN StartDate AND EndDate
        )

 END

【讨论】:

  • 如果参数为null,是否可以省略比较日期的条件?说@StartDate is null or (@StartDate between StartDate AND EndDate)。请原谅语法。
【解决方案3】:

你的事情过于复杂了。这应该对您有用,并且就像我所知道的那样简单的查询。我更喜欢这种语法,因为在我的大多数用例中, ...OR @UserName IS NULL 可以在查询执行之前从查询中删除,从而实现非常简单、快速的执行。

CREATE PROCEDURE  dbo.SP_ManageLeaveSearch

  @StartDate datetime,
  @EndDate datetime,

  @UserName CHAR(100), 
  @MarketID INT 

AS
BEGIN
SELECT d1.UserName,c1.HouseName,c.StartDate,c.EndDate
FROM table1 c    
JOIN table2 d1
    ON c.UserID = d1.UserID
WHERE (@StartDate<=EndDate OR @StartDate IS NULL)
AND (@EndDate>=StartDate OR @EndDate IS NULL)
AND (d1.UserName = @UserName OR @UserName IS NULL)
END

【讨论】:

  • 这个想法是,如果@StartDate@EndDate 都为NULL,则查询预处理器将在开始执行实际查询之前优化整个日期检查。如果一个为 NULL,而另一个不是,则查询将通过执行索引范围扫描以最佳方式使用 StartDate 和/或 EndDate 上的任何索引,对于 UserName 也是如此。 @UserName 如果它为 NULL 将在查询开始之前得到优化,如果它不是 NULL,那么它可以优化使用 UserName 列上的任何索引。
  • 当开始日期和结束日期都由用户输入时,此显示结果不正确
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-21
  • 2018-10-29
相关资源
最近更新 更多