有没有办法查询传递给存储过程的参数并将它们作为XML返回,而不创建参数字符串然后将其转换为xml?我正在寻找一些通用的东西,它适用于大多数SP,而不必每次都进行物理编码?
我有一堆存储过程可以访问和修改验证特定信息。在SP的末尾,我想在日志表中插入SP的名称,以及用于调用SP的参数(以xml为单位)。我知道如何获取SP的名称,我知道如何获取SP的参数列表。我想要的是一种方法,可以根据传递的参数的实际值将其全部混合到XML中。
我正在寻找能够做到这一点的事情,而不需要对每个参数进行手动编码:
DECLARE @L_Data varchar(1500)
SET @L_Data = '<parms>' +
CASE WHEN @ParamRegStationID IS NULL THEN ''
ELSE ',@ParamRegStationID=''' + Convert(varchar, @ParamRegStationID) + '''' END +
CASE WHEN @ParamScheduleID IS NULL THEN ''
ELSE ',@ParamScheduleID=''' + Convert(varchar, @ParamScheduleID) + '''' END +
CASE WHEN @ParamPatientID IS NULL THEN ''
ELSE ',@ParamPatientID=''' + Convert(varchar, @ParamPatientID) + '''' END +
CASE WHEN @ParamHISPatientID IS NULL THEN ''
ELSE ',@ParamHISPatientID=''' + @ParamHISPatientID + '''' END +
CASE WHEN @ParamEvent IS NULL THEN ''
ELSE ',@ParamEvent=''' + @ParamEvent + '''' END +
'</parms>'
这不起作用,并不像我希望的那样优雅。但是,这里有一个例子来说明我最终要做的事情。它创建临时表,但不会将参数作为列添加到它中,因此我可以稍后将其作为XML提取。
ALTER PROC uspTest
@ParamID as bigint=null,
@ParamXYZ as varchar(255)=null
as
-- PROC Does whatever it is going to do ....
DECLARE @ProcName varchar(128), @ParmName varchar(128), @ParmType varchar(128), @ParmLen int,
@ParmSQL varchar(1000)
select @ProcName=OBJECT_NAME(@@PROCID)
--select * from INFORMATION_SCHEMA.ROUTINES where ROUTINE_TYPE='PROCEDURE' and ROUTINE_NAME=@ProcName
DECLARE csrParms CURSOR
FOR
select PARAMETER_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH from INFORMATION_SCHEMA.PARAMETERS where SPECIFIC_NAME=@ProcName and PARAMETER_MODE='IN'
ORDER BY ORDINAL_POSITION
FOR READ ONLY
OPEN csrParms
FETCH NEXT FROM csrParms
INTO @ParmName, @ParmType, @ParmLen
CREATE TABLE #Parms(ID int identity(1,1), Created DateTime)
INSERT INTO #Parms select GETDATE()
WHILE @@FETCH_STATUS = 0
BEGIN
-- GET Parm value and format as xml attribute to save parm
SET @ParmSQL = 'ALTER TABLE #Parms add ' + @ParmName + ' varchar(' + CAST(ISNULL(@ParmLen, 128) as varchar(128)) + ') NULL '
print @ParmSQL
EXEC (@ParmSQL)
SET @ParmSQL = 'UPDATE #Parms SET ' + @ParmName + ' = ''????'''
print @ParmSQL
--EXEC (@ParmSQL)
FETCH NEXT FROM csrParms
INTO @ParmName, @ParmType, @ParmLen
END
SET @ParmSQL = CAST((select * from #Parms FOR XML RAW) as varchar(1000))
select @ParmSQL
CLOSE csrParms
DEALLOCATE csrParms
这接近我正在寻找的东西,我需要知道如何更换???但是动态地使用参数的当前值。
ALTER PROC uspTest
@ParamID as bigint=null,
@ParamXYZ as varchar(255)=null
as
-- PROC Does whatever it is going to do ....
DECLARE @ProcName varchar(128), @ParmName varchar(128), @ParmType varchar(128), @ParmLen int,
@ParmSQL varchar(1000)
select @ProcName=OBJECT_NAME(@@PROCID)
--select * from INFORMATION_SCHEMA.ROUTINES where ROUTINE_TYPE='PROCEDURE' and ROUTINE_NAME=@ProcName
set @ParmSQL =
' CREATE TABLE #Parms(ID int identity(1,1), Created DateTime, ' +
STUFF((select (', ' + REPLACE(PARAMETER_NAME,'@','') + ' varchar(' + CAST(ISNULL(CHARACTER_MAXIMUM_LENGTH, 128) as varchar(128)) + ') NULL ')
from INFORMATION_SCHEMA.PARAMETERS where SPECIFIC_NAME='uspTest' and PARAMETER_MODE='IN'
order by ORDINAL_POSITION for XML path(''), type).value('.', 'varchar(max)'), 1, 2, '')
+ ');
' + 'INSERT INTO #Parms (Created) select GETDATE(); ' + STUFF((select (';
UPDATE #Parms SET ' + REPLACE(PARAMETER_NAME,'@','') + ' = ''???''')
from INFORMATION_SCHEMA.PARAMETERS where SPECIFIC_NAME='uspTest' and PARAMETER_MODE='IN'
order by ORDINAL_POSITION for XML path(''), type).value('.', 'varchar(max)'), 1, 2, '')
+ ';
select CAST((select * from #Parms FOR XML RAW) as varchar(1000));'
print @ParmSQL
EXEC (@ParmSQL)
当我执行proc as:
时EXEC uspTest 1, 'test'
返回:
&lt; row ID =“1”Created =“2012-04-20T09:44:43.700”ParamID =“???” ParamXYZ = “???”/&GT;
打印出来:
CREATE TABLE #Parms(ID int identity(1,1), Created DateTime, ParamID varchar(128) NULL , ParamXYZ varchar(255) NULL );
INSERT INTO #Parms (Created) select GETDATE();
UPDATE #Parms SET ParamID = '???';
UPDATE #Parms SET ParamXYZ = '???';
select CAST((select * from #Parms FOR XML RAW) as varchar(1000));
答案 0 :(得分:0)
这是SQL Server 2000还是更高版本?如果是这样,您可以使用FOR XML子句:
DECLARE @p1 varchar(100) = 'blah'
, @p2 int = 1
, @p3 datetime2(7) = '2011-01-01 13:41'
;
SELECT @p1 StringParm
, @p2 IntParm
, @p3 DateParm
FOR XML RAW
返回:
<row StringParm="blah" IntParm="1" DateParm="2011-01-01T13:41:00"/>
修改强>
啊,问题在于您需要将参数列表以及值(本地值)解析为动态SQL(它们超出范围)。
我想您可以使用INFORMATION_SCHEMA.PARAMETERS动态列出参数,使用dbcc_inputbuffers来获取传递的实际值。类似的东西:
create procedure junk
( @int INT
, @string VARCHAR(20)
, @date DATE
)
AS
BEGIN
DECLARE @tmp TABLE
( EventType NVARCHAR(30)
, PARMS INT
, Info NVARCHAR(2000)
);
DECLARE @object NVARCHAR(200);
INSERT INTO @tmp
EXEC('DBCC INPUTBUFFER(@@SPID) WITH NO_INFOMSGS');
SELECT INFO
, 'Call' lType
FROM @tmp
UNION
SELECT STUFF(
( SELECT ', ' + parameter_name
FROM INFORMATION_SCHEMA.PARAMETERS
WHERE SPECIFIC_NAME = OBJECT_NAME(@@procid)
ORDER BY ORDINAL_POSITION
FOR XML PATH('')
)
, 1
, 2
, ''
)
, 'Parms';
END
现在这样做:
exec dbo.junk @int = 3, @string = 'hoo', @date = '2/2/2002';
返回:
exec dbo.junk @int = 3, @string = 'hoo', @date = '2/2/2002'; Call
@int, @string, @date Parms
哪个可以帮到你。棘手的是DBCC_INPUTBUFFERS返回EXACT调用字符串。因此,您需要编写代码来解析调用以将输入行与参数列表匹配。如果你走这条路,你可能想要一个存储函数进行解析。它可能会使调用字符串和参数列表与上面的返回值类似,匹配它们,并使用FOR XML子句返回所需的格式。
您还可以解析绑定到参数列表的游标中的调用字符串。然后你按顺序拉出参数并查找逗号和@。如果不考虑这些字符,您仍可能遇到包含这些字符的参数值的问题。
恕我直言,相比于一个几乎可以从函数头中复制/粘贴的简单选择,这种平方似乎要做很多工作。当然,如果你在谈论大量的程序,那么它可能是值得的。无论哪种方式,祝你好运,并感谢一个发人深思的问题。