为什么不能将 GETDATE() 用作过程参数的默认值或 EXECUTE 语句中的值?

Mik*_*fer 7 t-sql sql-server

考虑以下存储过程:

CREATE OR ALTER PROCEDURE MySchema.MyProcedure
   @myDateTimeParam DATETIME = GETDATE()
AS
BEGIN
   -- Do something spectacular
END
Run Code Online (Sandbox Code Playgroud)

调用时,参数声明失败并显示错误“将数据类型 nvarchar 转换为日期时出错”。这可以通过如下更改代码来解决:

CREATE OR ALTER PROCEDURE MySchema.MyProcedure
   @myDateTimeParam DATETIME = NULL
AS
BEGIN

    IF @myDateTimeParam IS NULL
        SET @myDateTimeParam = GETDATE();

   -- Do something spectacular
END
Run Code Online (Sandbox Code Playgroud)

但是,假设@myDateTimeParam没有默认值:

CREATE OR ALTER PROCEDURE MySchema.MyProcedure
   @myDateTimeParam DATETIME
AS
BEGIN
   -- Do something spectacular
END
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您不能简单地GETDATE()作为形式参数传递,如下所示:

EXEC MySchema.MyProcedure GETDATE()
Run Code Online (Sandbox Code Playgroud)

因为这也会产生可怕的“将数据类型 nvarchar 转换为日期时出错”的错误。唯一的解决方法是首先声明一个变量,然后传递该变量:

DECLARE @myDateTimeParam DATETIME = GETDATE();
EXEC MySchema.MyProcedure @myDateTimeParam;
Run Code Online (Sandbox Code Playgroud)

为什么是这样?源数据类型和目标数据类型都是DATETIME. 理论上,GETDATE()无论是作为参数的默认值还是形参的值,都不会发生数据类型转换错误。

是否有一些技术原因这不起作用?MSDN 文档中没有任何内容表明它不应该工作。

use*_*983 7

这在文档CREATE PROCEDURE (Transact-SQL)中包含在参数部分的默认副标题下:

参数的默认值。如果为参数定义了默认值,则无需为该参数指定值即可执行该过程。默认值必须是常量,也可以是 NULL。常量值可以采用通配符的形式,从而可以在将参数传递到过程中时使用 LIKE 关键字。

强调我的。

GETDATE()不是常数,因此不能用作 aDEFAULT值。因此,为什么您需要使用以下格式,因为 的值GETDATE()是在运行时确定的:

CREATE PROC YourProc @Param date = NULL
AS

    IF @Param IS NULL BEGIN
        SET @Param = GETDATE();
    END;
    ...
Run Code Online (Sandbox Code Playgroud)

  • 刚刚在`EXECUTE` 文档中发现了这一点:“如果你传递一个不以@ 开头并且没有用引号括起来的单词——例如,**如果你忘记了参数名称上的@——这个词被视为一个 nvarchar 字符串,尽管缺少引号**。” 我想这就解释了。 (3认同)