第1部分
DECLARE @A INT
DECLARE @B NVARCHAR(20)
SET @A=123
SET @B='@A'
第2部分
DECLARE @SQL NVARCHAR(MAX)
SET @SQL='SELECT ' + @B
EXEC SP_EXECUTESQL @SQL
--Should return 123
在非动态SQL中直接引用@A对于此任务是不可接受的。
第2部分中的上述内容通常是我想要做的。我理解变量超出了范围,它不会像上面那样工作。我怎么能用@B来获得@A的价值?
更新20190322 : 我实际上忘记了这个问题,并在C#端而不是数据库上实现了日志记录,但如果可能的话,我又好奇了。同样,这需要是通用的,因为我想把它放到任何存储过程的顶部,我不想为每个sproc定制它;我在光标中获取参数值时遇到了麻烦。这是一个有效的例子:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[LoggingTest]
@DateBegin datetime,
@DateEnd datetime,
@Person varchar(8000),
@Unit varchar(8000)
AS
BEGIN
--BEGIN LOGGING CODE
DECLARE @String NVARCHAR(MAX)=''
DECLARE @Parameter_name nvarchar(2000), @type nvarchar(50), @length SMALLINT, @Prec SMALLINT, @Scale SMALLINT, @Param_order SMALLINT, @Collation nvarchar(2000);
DECLARE param_cursor CURSOR FOR
SELECT
'Parameter_name' = name,
'Type' = type_name(user_type_id),
'Length' = max_length,
'Prec' = case when type_name(system_type_id) = 'uniqueidentifier'
then precision
else OdbcPrec(system_type_id, max_length, precision) end,
'Scale' = OdbcScale(system_type_id, scale),
'Param_order' = parameter_id,
'Collation' = convert(sysname,
case when system_type_id in (35, 99, 167, 175, 231, 239)
then ServerProperty('collation') end)
from sys.parameters
where object_id = object_id(OBJECT_NAME(@@PROCID))
OPEN param_cursor
FETCH NEXT FROM param_cursor
INTO @Parameter_name,@type,@length,@Prec,@Scale,@Param_order,@Collation
WHILE @@FETCH_STATUS = 0
BEGIN
SET @String=@String + @Parameter_name + '==' --+ SELECT @Parameter_name --This is part I can't think of a way to do; need to record/capture the value
SET @String=@String + CHAR(13) + CHAR(10)
FETCH NEXT FROM param_cursor
INTO @Parameter_name, @type,@length,@Prec,@Scale,@Param_order,@Collation
END
CLOSE param_cursor;
DEALLOCATE param_cursor;
--INSERT DATA INTO LOG TABLE HERE
SELECT OBJECT_SCHEMA_NAME(@@PROCID) + '.' + OBJECT_NAME(@@PROCID) AS [ProcedureName],@String AS [Data],GETDATE() AS [LogTime]
--END LOGGING CODE
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
DO BUSINESS STUFF HERE!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
/*
BLAH
BLAH
BLAH
DECLARE @Now DATETIME=GETDATE()
EXEC [dbo].[LoggingTest] @Now,@Now,'Person Value','Unit Value'
*/
END
GO
答案 0 :(得分:5)
我不明白你问的所有事情,但你可以在sp_executesql
上定义变量:
EXEC SP_EXECUTESQL @SQL, N'@A INT', @A = @A
答案 1 :(得分:1)
虽然你不必这样做,但仍然是这样:
SET @B=@A
您可以直接指定@A的值:
DECLARE @SQL NVARCHAR(MAX)
SET @SQL='SELECT ' + Convert(varchar(50),@A)
答案 2 :(得分:1)
搜索后,我发现一个可以
具有dm_exec_requests
和dm_exec_sql_text
具有来自dm_exec_input_buffer
的过程调用。我应该指出,我对此并不十分精通,而且我认为我在某处阅读过的文章不适用于在SSMS之外完成的查询。...
在代码中已经看到,可以在sys.parameters
因此,我实现了一种方法。算法的主要步骤是:
- 使用相同的参数和默认值创建一个虚拟proc。将其主体更改为单个
SELECT
。通过在原始proc上使用一个动态xml级联的参数,该过程高一级,我们可以为虚拟proc提供一个VALUES
表,其中包含参数名称(用引号引起来)和它们的值(没有引号) 。- 通过使用原始spc中使用的相同调用参数来执行虚拟proc。将
INSERT
的{{1}}结果集放入临时表。删除虚拟进程 之后。
现在我们有了一个同时包含参数名称和值的临时表。
大多数新代码都在您开始之前,除了您在游标中所需的实际值之外。另外,为了避免进行激烈的解析,我使用了(便宜的)技巧,在EXEC
之后添加了注释--postBeginParserMarker
,以便我知道proc从哪里开始...
BEGIN
答案 3 :(得分:1)
从SQL Server 2014 SP2开始,有一个sys.dm_exec_input_buffer
动态管理视图。
在以前的版本中,有DBCC INPUTBUFFER
。
它返回一个表,该表包含一列event_info
,其中包含“给定spid在输入缓冲区中的语句文本。”
因此,您可以向存储过程的开头添加一个简单的查询,如下所示:
INSERT INTO LoggingTable(event_info, event_type, parameters)
SELECT
InBuf.event_info
,InBuf.event_type
,InBuf.parameters
FROM
sys.dm_exec_requests AS Req
INNER JOIN sys.dm_exec_sessions AS Ses ON Ses.session_id = Req.session_id
CROSS APPLY sys.dm_exec_input_buffer(Req.session_id, Req.request_id) AS InBuf
WHERE
Ses.session_id > 50
AND Ses.is_user_process = 1
;
如果您使用EXEC
调用/运行存储过程,例如
EXEC [dbo].[LoggingTest]
@DateBegin = '2019-01-01',
@DateEnd = '2020-01-01',
@Person = 'person name',
@Unit = 'some unit';
然后,event_info
将包含EXEC
查询的确切文本。我的意思是上面的文字。 EXEC [dbo].[LoggingTest] @DateBegin = '2019-01-01', @DateEnd = '2020-01-01', @Person = 'person name', @Unit = 'some unit';
显然,它包含参数的值,不需要解析任何内容或执行其他任何技巧。足以记录日志。
很酷。事件类型将为“语言事件”。
不幸的是,如果使用RPC(通常在C#代码中发生)来“适当地”调用存储过程,那么您得到的仅仅是该存储过程的名称。
event_info
。像这样:
YourDatabaseName.dbo.LoggingTest
这里不会提及参数和/或它们的值:-(事件类型为“ RPC事件”。
parameters
列为smallint
,在我的测试中始终包含0
。文档尚不清楚如何理解这一点。