2

不知道如何实现这一点,但我需要一种方法来获取存储过程的当前参数列表以及它们传入的值(此代码将在存储过程本身中执行)。

我知道我可以sys.parameters用来获取参数名称,但是如何获取实际值呢?

我需要做的是制作一个 char 形式的字符串

@param_name1=@value1,@param_name2=@value2,...,@param_namen=@valuen

我曾尝试使用动态 sql,但对此并不满意。

有任何想法吗??

编辑:

目前我只是一个一个地检查所有参数来构建字符串。但是我想要一种“更好”的方式来做到这一点,因为有很多参数。并且稍后会添加 incase 参数(但不会更新生成字符串的代码)。

我尝试使用动态 sql 但放弃了,因为sp_executesqlsp 需要将参数传递给它......

4

2 回答 2

3

您声明'(此代码将在存储过程本身中执行)。因此,假设您在过程中,您将已经知道参数名称,因为您必须在创建过程时声明它们。只需进行选择并将名称放在文本字段中

ALTER PROCEDURE procname
(
     @param1 NVARCHAR(255)
    ,@param2 INT
    ...
)

SELECT [Parameters] = '@param1=' + @param1 
                    + ',@param2=' + CONVERT(NVARCHAR(MAX),@param2)...

CONVERT是非字符数据类型的示例。


更新

您需要创建一个指向自身的链接服务器才能使用该OPENQUERY功能。

USE [master]
GO

/****** Object:  LinkedServer [.]    Script Date: 04/03/2013 16:22:13 ******/
EXEC master.dbo.sp_addlinkedserver @server = N'.', @srvproduct=N'', @provider=N'SQLNCLI', @datasrc=N'.', @provstr=N'Integrated Security=SSPI'
 /* For security reasons the linked server remote logins password is changed with ######## */
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'.',@useself=N'True',@locallogin=NULL,@rmtuser=NULL,@rmtpassword=NULL

GO

现在您可以执行类似此游标的操作来获取每个参数名称,然后使用动态 sql inOPENQUERY获取值:

DECLARE curParms CURSOR FOR
SELECT
    name
FROM sys.parameters
WHERE OBJECT_ID = OBJECT_ID('schema.procedurename')
ORDER BY parameter_id
OPEN curParms
FETCH curParms INTO @parmName
WHILE @@FETCH_STATUS <> -1
BEGIN
    SELECT @parmName + '=' + (SELECT * FROM OPENQUERY('linkedservername','SELECT ' + @parmName))
    FETCH curParms INTO @parmName
END
CLOSE curParms
DEALLOCATE curParms
于 2013-03-04T13:02:02.170 回答
1

从 SQL Server 2014 开始sys.dm_exec_input_buffer,它是一个表值函数,带有一个输出列event_info,提供完整的执行语句(包括参数)。

我们可以从中解析参数值sys.dm_exec_input_buffer并从中获取参数名称sys.parameters并将它们连接在一起以获得您想要的字符串。

例如:

create procedure [dbo].[get_proc_params_demo]
(
    @number1 int,
    @string1 varchar(50),
    @calendar datetime,
    @number2 int,
    @string2 nvarchar(max)
)
as
begin

-- get the full execution statement
declare @statement nvarchar(max)
select  @statement = event_info
from    sys.dm_exec_input_buffer(@@spid, current_request_id())

-- parse param values from the statement
declare @proc_name varchar(128) = object_name(@@procid)
declare @param_idx int = charindex(@proc_name, @statement) + len(@proc_name)
declare @param_len int = len(@statement) - @param_idx 
declare @params nvarchar(max) = right(@statement, @param_len)

-- create param values table
select  value, row_number() over (order by current_timestamp) seq
into    #params
from    string_split(@params, ',')

-- get final string
declare @final nvarchar(max)
select  @final = isnull(@final + ',','') + p1.name + '=' + ltrim(p2.value)
from    sys.parameters p1
        left join #params p2 on p2.seq = parameter_id
where   object_id = @@procid

select  @final params
end

要测试它:

exec get_proc_params_demo 42, 'is the answer', '2019-06-19', 123456789, 'another string'

返回你想要的字符串:

@number1=42,@string1='is the answer',@calendar='2019-06-19',@number2=123456789,@string2='another string'

我有类似的东西包装成 UDF。我用它来记录 catch 块中的错误。

于 2019-06-19T18:58:21.147 回答