从 SQL 服务器执行带有可为空参数的存储过程

Execute stored procedure with a nullable parameter from SQL server

我有一个带有多个参数的存储过程 MYTASK1。它被称为这样的:

EXECUTE MYTASK1 '2021' , '1','1'

如果参数为 null,我如何 运行 存储过程。我试过了

EXECUTE MYTASK1 '2021' , '' ,''

但它什么也没做。

我的存储过程

ALTER PROC MYTASK1 @Year varchar(6) = NULL,
                   @quarter varchar(6) = NULL,
                   @month varchar(6) = NULL
AS
BEGIN

    SELECT 'Sell Out' AS name,
           'Total Sales Amount' AS Description,
           'down' AS status,
           CAST(SUM(NetValue) AS decimal(9, 2)) AS amount
    FROM SalesAndReturns_RPT
    GROUP BY YEAR(Call_ActualStartDate),
             DATEPART(QUARTER, Call_ActualStartDate),
             MONTH(Call_ActualStartDate)
    HAVING YEAR(Call_ActualStartDate) = @Year
       AND DATEPART(QUARTER, Call_ActualStartDate) = @quarter
       AND MONTH(Call_ActualStartDate) = @month;

END;

您正在执行的代码:EXECUTE MYTASK1 '2021' , '' ,'' 以空字符串作为参数触发过程 MYTASK1。请注意,空字符串是不是与 null 不同的值... NULL 是缺少值,而空字符串是完全有效的字符串 ;)

你可以试试 EXECUTE MYTASK1 '2021' , NULL ,NULL

在你的例子中,NULL 是一个默认值,所以你也可以使用: EXECUTE MYTASK1 '2021'

这是一个猜测,但我认为这就是您想要的:

ALTER PROC dbo.MYTASK1 @Year int = NULL, --Makes no sense as a varchar(6)
                       @Quarter int = NULL, --Makes no sense as a varchar(6)
                       @Month int = NULL --Makes no sense as a varchar(6)
AS
BEGIN

    SELECT 'Sell Out' AS name,
           'Total Sales Amount' AS Description,
           'down' AS status,
           CAST(SUM(NetValue) AS decimal(9, 2)) AS amount
    FROM dbo.SalesAndReturns_RPT
    WHERE ((Call_ActualStartDate >= DATEFROMPARTS(@Year, 1, 1) AND Call_ActualStartDate < DATEFROMPARTS(@Year+1, 1, 1)) OR @Year IS NULL)
      AND (DATEPART(QUARTER, Call_ActualStartDate) = @Quarter OR @Quarter IS NULL)
      AND (DATEPART(MONTH,Call_ActualStartDate) = @Month OR @Month IS NULL)
    OPTION (RECOMPILE);

END;

我已经为 @Year SARGable 创建了子句,但是,没有关于如果 @Year 是 [=15] 应该如何处理 @month@quarter 的信息=] 那么这可能没什么区别,因为这些子句不可 SARGable。我 假设 如果 @YearNULL@Month 不是,你会想要 SUM 中的所有行月份,无论它属于哪一年。

如果您确实需要针对此要求的 SARGable 解决方案,则需要实施日历 table。

因为你有 NULL 作为默认值,你可以根本不提供参数值

EXECUTE MYTASK1 '2021'

相同
EXECUTE MYTASK1 '2021', NULL, NULL

您也可以像这样使用命名参数:

EXECUTE MYTASK1 @quarter='Q1'

但是,根据其他答案和评论,您对存储过程的内容存在实质性问题。