TL;DR
仅当有人找到一种从变量名中获取变量值的方法时。
回答
可以创建类型表的新数据类型并将其用作错误跟踪存储过程的输入。在该变量中,每个参数都有一行名称和值。
一个例子是
CREATE TYPE _stored_param AS TABLE (
Name varchar(50)
, [Value] sql_Variant
)
GO
CREATE PROCEDURE printParam (@sentParam _stored_param READONLY) AS
BEGIN
SELECT * FROM @sentParam
END
GO
CREATE PROCEDURE myProcedure (@param VARCHAR(10)) AS
BEGIN
DECLARE @myParam AS _stored_param;
INSERT INTO @myParam (Name, [Value]) VALUES ('@param', @param)
EXEC printParam @myParam;
END
GO
EXEC myProcedure 'foo'
myProcedure 的执行结果,done last line 会得到你
Name Value
------- -------
@param foo
酷! ...但INSERT 是静态的,每次更改或添加存储过程参数时,INSERT 也需要更改。
我们可以更改过程以创建动态INSERT,使用INFORMATION_SCHEMA.PARAMETERS 获取参数名称,使用OBJECT_NAME(@@PROCID) 在WHERE 条件下仅获取当前过程的参数名称。
初始 SP
CREATE PROCEDURE Inception (@param1 VARCHAR(10), @param2 INT)
AS
BEGIN
DECLARE @paramQuery as NVARCHAR(MAX);
DECLARE @paramVar as _stored_param;
DECLARE @execVar as NVARCHAR(MAX);
SET @paramQuery = '';
SELECT @paramQuery
+= 'SELECT ''' + PARAMETER_NAME
+ ''', CAST(' + PARAMETER_NAME + ' AS SQL_VARIANT) UNION ALL '
FROM INFORMATION_SCHEMA.PARAMETERS
WHERE SPECIFIC_NAME = OBJECT_NAME(@@PROCID)
ORDER BY ORDINAL_POSITION
SET @paramQuery = LEFT(@paramQuery, len(@paramQuery) - 10);
SET @execVar = ''
SELECT @execVar
+= PARAMETER_NAME + ' ' + DATA_TYPE
+ ISNULL('(' + CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR) + '), ', ', ')
FROM INFORMATION_SCHEMA.PARAMETERS
WHERE SPECIFIC_NAME = OBJECT_NAME(@@PROCID)
ORDER BY ORDINAL_POSITION
SET @execVar = LEFT(@execVar, LEN(@execVar) - 1);
INSERT INTO @paramVar
EXEC sp_executesql @paramQuery, @execVar, @param1, @param2
SELECT * from @paramVar
END
GO
EXEC Inception 'foo', 2;
在此存储过程中,变量 @paramQuery 被计算为字符串
SELECT '@param1', CAST(@param1 AS SQL_VARIANT)
UNION ALL
SELECT '@param2', CAST(@param2 AS SQL_VARIANT)
但作为一个动态查询,它需要被执行。
执行动态查询就像调用另一个存储过程:您需要在需要时传递参数,并且执行是在隔离级别上执行的,其中调用者变量不可见。
这意味着要执行查询以获取参数值,您需要将参数值作为参数传递。
唯一的好处是,当存储过程被更改更改参数号时,查询将产生类似的错误
Msg 8178, Level 16, State 1, Line 39
The parameterized query '(@param1 varchar(10), @param2 int)SELECT '@param1', CAST(@param1' expects the parameter '@param2', which was not supplied.
要求检查sp_executesql参数段落。
其他方法,如使用参数的名称和值创建字符串或使用参数的名称和值创建 XML 将碰壁:获取给定变量名称的变量值作为字符串 (varchar) .