我在 SQL Server 上有一个存储过程,它有3个参数,都是可选的。
参数为month
,year
和class
(仅作为示例)。
如果没有通知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'
答案 0 :(得分:3)
一种可能的解决方案是:
WHERE V.CLASS = ISNULL(@class, V.CLASS)
这意味着:V.CLASS = @class
或(如果@class
为null
)V.CLASS = V.CLASS
,则始终为真。
顺便说一句:您的查询可能不具备性能,因为MONTH
和YEAR
的使用不允许使用索引。
而是创建您想要返回的月份的第一个月和下个月的第一个月:
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