【发布时间】:2010-09-13 04:46:19
【问题描述】:
有没有什么方法可以引用传递给存储过程的参数集合,而不用名称来引用每个参数?
这里的上下文是错误记录。我想开发一个通用的 CATCH 子句或子子句,它可以获取所有参数值以及其他错误和执行信息并将其记录到一个表中(一个或多个)。
基本版本如下所示:
CREATE PROC dbo.Proc1 @Param1 INT, @Param2 INT
AS
BEGIN TRY
SELECT 1/0
END TRY
BEGIN CATCH
DECLARE @params XML
SET @params = (
SELECT
@Param1 AS [Param1]
, @Param2 AS [Param2]
FOR XML PATH('params'), TYPE
)
EXEC dbo.LogError @procid = @@PROCID, @params = @params
EXEC dbo.RethrowError
END CATCH
现在,这个模板确实有效,除了对于每个单独的过程,我必须手动编辑 SET @params 部分。
我可以很容易地把它写出来,但我仍然需要把它复制进去。
我可以留下某种占位符,然后使用正确的SET 语句动态更新每个定义。我什至可以编写一个数据库触发器来侦听 CREATE 和 ALTER PROC 语句,并让它自动为我执行此操作。
但我真正想要的只是直接获取参数集合并完成它。有什么办法吗?
编辑:从系统表中获取参数元数据是不够的。例如:
DECLARE @sql NVARCHAR(MAX)
SET @sql =
'SET @params = (SELECT '
+ STUFF((
SELECT ', '+name+' AS '+STUFF(name,1,1,'')
FROM sys.parameters WHERE object_id = @@PROCID
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)')
,1,2,'')
+ ' FOR XML PATH(''params''), TYPE)'
-- inline execute here....alas, there's isn't a mode for that
EXEC sp_executesql @sql, N'@params XML OUTPUT', @params OUTPUT
这当然会产生错误,因为我没有为sp_executesql 的嵌套范围声明参数。虽然我可以编写出sp_executesql 的第二个参数,但如果不按名称一次明确地分配一个参数,我就无法分配它们。
原始问题,改写:是否有另一种sp_executesql 从外部范围继承变量“上下文”,在同一帧中执行,内联命令,而不是在嵌套范围?
【问题讨论】:
-
对于什么版本的 SQL Server?表变量或用户定义类型可能做你想做的事,但你仍然需要填充它们。
-
@OMG Ponies,无论我现在如何接近它,我都无法摆脱显式变量引用 somewhere。为什么 T-SQL 没有 $frame 或 $variables 特殊变量?唉。
-
@Peter:您想要的方法是等待发生的 SQL 注入攻击——SQL/TSQL 正在保护您免受自己的侵害。
-
@OMG Ponies:向我展示一个不存在的 $frame 特殊变量引入的攻击向量。我们没有执行任意代码。
EXEC ()和sp_executesql已经很方便地提供了该向量。 -
EXEC或sp_executesql阻止我通过DELETE FROM USER/等。两者都不会在运行 SQL 之前对其进行验证...
标签: tsql sql-server-2008 metaprogramming