有条件的存储过程

时间:2016-12-09 11:44:52

标签: sql-server stored-procedures sql-server-2016

我在 SQL Server 上有一个存储过程,它有3个参数,都是可选的。 参数为monthyearclass(仅作为示例)。

如果没有通知month的值,那么默认值将是当前月份,对于year,默认值将是当前年份。

然后在课堂上,如果没有通知任何价值,则不会使用where条件,或者至少要WHERE class IS NOT NULL(必须返回所有class)。

存储过程根据参数运行select。

存储过程:

CREATE PROCEDURE [dbo].[SP_TEST]
    @month INT,
    @year INT,
    @class NVARCHAR(10) = NULL
AS
BEGIN
    SET NOCOUNT ON

    IF @month IS NULL
        SET @month = MONTH(GETDATE())

    IF @year IS NULL
        SET @year = YEAR(GETDATE())

    SELECT
        *
    FROM 
        TABLE_TEST V
    WHERE
        MONTH(V.DATE) = @month AND
        YEAR(V.DATE) = @year AND
        CLASS = ???

所以,在WHERE中,我尝试了以下代码:

代码01:

WHERE
    MONTH(V.DATE) = @month AND
    YEAR(V.DATE) = @year AND
    (@class IS NOT NULL AND CLASS = @class)

结果:

  • 如果我将值传递给@class,那么一切正常

  • 如果我将NULL传递给@class,则不会返回任何内容。

代码02:

WHERE
    MONTH(V.DATE) = @month AND
    YEAR(V.DATE) = @year AND
    V.CLASS = CASE WHEN @class != NULL THEN @class END

结果:

  • 如果我将值传递给@class,则不会返回任何内容。

  • 如果我将NULL传递给@class,则不会返回任何内容。

我如何调用存储过程:

NULL上的class

EXEC [dbo].[SP_TEST]
    @month = NULL,
    @year = NULL,
    @class = NULL

有些class

EXEC [dbo].[SP_TEST]
    @month = NULL,
    @year = NULL,
    @class = 'TEST_A'

3 个答案:

答案 0 :(得分:3)

一种可能的解决方案是:

WHERE V.CLASS = ISNULL(@class, V.CLASS)

这意味着:V.CLASS = @class或(如果@classnullV.CLASS = V.CLASS,则始终为真。

顺便说一句:您的查询可能不具备性能,因为MONTHYEAR的使用不允许使用索引。

而是创建您想要返回的月份的第一个月和下个月的第一个月:

DECLARE @monthStart DATETIME
DECLARE @monthEnd DATETIME
SET @monthStart = DATETIMEFROMPARTS
                  (
                    ISNULL(@year, YEAR(GETDATE())), 
                    ISNULL(@month, MONTH(GETDATE())), 
                    1, 
                    0,
                    0, 
                    0, 
                    0
                  )
SET @monthEnd = DATEADD(mm, 1, @monthStart)

我的建议是计算当年请求月份的第一个日期和最后日期,然后使用

WHERE V.DATE >= @monthStart AND V.DATE < @monthEnd

答案 1 :(得分:1)

你的代码应该在什么样的地方之后

WHERE
     MONTH(V.DATE) = @month AND
     YEAR(V.DATE) = @year AND
     @class IS NULL OR V.CLASS = @class

答案 2 :(得分:0)

你可以用这个

WHERE      MONTH(V.DATE)= @month AND      年(V.DATE)= @year AND

 class = case
 when class=@class then @class
 else table_name.class