处理存储过程中的可选参数

And*_*ndy 4 sql-server stored-procedures t-sql parameter

我有一个存储过程,用可选参数@Param1 int = NULL 说“测试”。在该过程中,@Param1 的值用于更新某个表中某个列的值,如果调用者提供了一个值。如果未提供该参数,则不会更新该列。不幸的是,该列允许 NULL,因此调用者无法将列值设置为 NULL。所以,问题是:程序是否能够区分以下两个调用?

EXEC Test -- 预期含义:不更新列

EXEC Test @Param1 = NULL -- 预期含义:将列设置为 NULL

当然,程序可以检查是否@Param1 IS NULL。但是它可以确定是否已经提供了参数吗?

小智 5

也许这样的事情可能会奏效:-

CREATE PROC dbo.Test @Param1 INT = NULL
AS
BEGIN
    SET NOCOUNT ON;

    IF EXISTS
    (
        SELECT 1
        FROM sys.dm_exec_requests AS ER
            CROSS APPLY sys.dm_exec_input_buffer(ER.session_id, ER.request_id) AS IB
        WHERE ER.session_id = @@SPID
              AND IB.event_info LIKE '%@Param1%'
    )
    BEGIN
        IF @Param1 IS NULL
        BEGIN
            RAISERROR('@Param1 was supplied as NULL', 0, 1) WITH NOWAIT;
        END;
        ELSE
        BEGIN
            RAISERROR('@Param1 was supplied as a non-NULL value', 0, 1) WITH NOWAIT;
        END;
    END;
    ELSE
    BEGIN
        RAISERROR('@Param1 was not supplied and defaulted to NULL', 0, 1) WITH NOWAIT;
    END;
END;
GO
Run Code Online (Sandbox Code Playgroud)

测试:-

EXEC dbo.Test @Param1 = NULL;
GO
EXEC dbo.Test @Param1 = 123;
GO
EXEC dbo.Test;
GO
Run Code Online (Sandbox Code Playgroud)

结果(在 15.0.4102.2 上):-

CREATE PROC dbo.Test @Param1 INT = NULL
AS
BEGIN
    SET NOCOUNT ON;

    IF EXISTS
    (
        SELECT 1
        FROM sys.dm_exec_requests AS ER
            CROSS APPLY sys.dm_exec_input_buffer(ER.session_id, ER.request_id) AS IB
        WHERE ER.session_id = @@SPID
              AND IB.event_info LIKE '%@Param1%'
    )
    BEGIN
        IF @Param1 IS NULL
        BEGIN
            RAISERROR('@Param1 was supplied as NULL', 0, 1) WITH NOWAIT;
        END;
        ELSE
        BEGIN
            RAISERROR('@Param1 was supplied as a non-NULL value', 0, 1) WITH NOWAIT;
        END;
    END;
    ELSE
    BEGIN
        RAISERROR('@Param1 was not supplied and defaulted to NULL', 0, 1) WITH NOWAIT;
    END;
END;
GO
Run Code Online (Sandbox Code Playgroud)

@@ SPIDCURRENT_REQUEST_ID可用于提供的参数sys.dm_exec_input_buffer。在当前会话中使用该 DMV 不需要特殊权限。需要更多权限才能查看其他会话的详细信息。

  • [此网络](https://dba.stackexchange.com/a/103275/68127) 和[外部](http://blog.sqlxdetails .com/procedure-with-execute-as-login/)。作为解决所问问题的概念证明,这是正确的答案,应该被接受。 (2认同)