如何将 DATE 参数默认设置为 SQL 服务器中的动态计算值

How to set DATE parameter default to dynamically calculated value in SQL Server

我有一个包含两个 DATE 参数的存储过程,我希望它们具有默认值。但是,我也希望能够根据需要覆盖这些值。我正在使用 SSMS 18。下面是我希望我的代码如何工作。 (这不是一个工作示例)

CREATE PROCEDURE dbo.usp_stuff_and_things
    -- Add the parameters for the stored procedure here
     @begin_date DATE = (SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0) )
     ,@end_date DATE = (SELECT DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE())-1, -1) )
    
AS
BEGIN

    SET NOCOUNT ON;

    -- Insert statements for procedure here
    

这两个参数分别是抢上月的第一天(@begin_date)和上月的最后一天(@end_date)。这些默认值大部分时间都有效,但有时我需要拉出自定义日期范围。我希望能够根据需要将这样的值传递给存储过程。

EXEC dbo.usp_stuff_and_things @begin_date = '2021-01-01', @end_date = '2021-12-31'

有没有办法做到这一点?

默认值不能使用表达式。尝试:

CREATE PROCEDURE dbo.usp_stuff_and_things
    @begin_date date = NULL,
    @end_date   date = NULL   
AS
BEGIN
  SET NOCOUNT ON;
  
  SET @end_date   = COALESCE(@end_date, 
        EOMONTH(GETDATE(), -2));

  SET @begin_date = COALESCE(@begin_date,
        DATEADD(DAY, 1, @end_date));
END
GO

EOMONTH() 在大多数情况下恕我直言,没有太多价值,但它是一种动态确定月份边界的简单方法。其他一些比混乱和神秘的 dateadd/datediff 方法更好的方法:

我也真的建议避免使用 yyyy-mm-dd 格式,因为它在某些情况下可能会被误解为 yyyy-dd-mm:

虽然我不得不说,结束日期后一天的开始日期没有多大意义。

过程DEFAULT值必须是文字,不能是表达式,当然不能从[=12解析=] 语句。相反,您可以 DEFAULT 将值 NULL 赋值给过程定义中的表达式,如果值为 NULL:

CREATE PROCEDURE dbo.usp_stuff_and_things
    -- Add the parameters for the stored procedure here
     @begin_date DATE = NULL,
     @end_date DATE = NULL
AS
BEGIN

    SET NOCOUNT ON;

    IF @begin_date IS NULL
        SET @begin_date = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0);

    IF @end_date IS NULL
        SET @end_date = DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE())-1, -1);

    -- Insert statements for procedure here

END;
GO