【问题标题】:Pass stored procedure parameter values to nested stored procedure without knowing parameter names在不知道参数名称的情况下将存储过程参数值传递给嵌套存储过程
【发布时间】:2014-04-22 15:21:11
【问题描述】:

我正在尝试创建一个在所有存储过程中调用的通用错误捕获存储过程,并且我需要获取所有参数名称(我可以从系统表中执行此操作,只知道存储过程名称)和值。

这些值是我真正需要动态获取和获取的值(无需专门按名称将它们传递给存储过程)。

是否有某种方法可以将唯一 ID 或其他东西传递给嵌套存储过程,我可以使用它来获取嵌套存储过程中主存储过程的参数值?

简短的例子:我有一个存储过程:

create PROCEDURE testParamaters
    @text1 VARCHAR(500),
    @DateTime1 DATETIME
AS

-- I want to be able to call an SP something like this:
EXEC DynamicErrorTrackingSP (pass something, system variable/data/etc, so I can 
                             dynamically get all parameter values in nested SP)

我目前有与此类似的代码,它工作正常(但必须为每个 SP 编辑它才能正确传递参数值(我不想为每个 SP 都编辑它)。

EXEC DynamicErrorTrackingSP @ParmaterNameValuePairs = 
     '@text1 = ' + @text1 + ', @DateTime1 = ' + cast(@DateTime1 as varchar(500)) + ''

【问题讨论】:

  • 以上2个链接是我已经知道(并且正在使用)的东西,但我需要知道如何获取参数值以及参数名称(我可以得到)
  • 这些值是运行时变量,我认为没有办法让它们在当前存储过程之外运行而不传递它们。
  • 是否可以发送完整的变量名称/值对集合,而不必专门调用每个变量和名称到我要发送到的过程?

标签: sql stored-procedures error-handling sql-server-2012


【解决方案1】:

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) .

【讨论】:

    猜你喜欢
    • 2016-04-05
    • 1970-01-01
    • 2011-07-12
    • 1970-01-01
    相关资源
    最近更新 更多