如何获取dm_exec_sql_text的参数值

时间:2010-03-24 16:04:50

标签: sql-server sql-server-2005 sql-server-2008

我正在运行以下语句,以查看在sql server中执行的查询:

select *
from sys.dm_exec_requests r
cross apply sys.dm_exec_sql_text(r.sql_handle)
where r.database_id = DB_ID('<dbname>')

返回的sql文本已参数化:

(@Parm0 int) select * from foo where foo_id = @Parm0

有没有办法获取语句正在使用的参数的值?或许加入另一张桌子说?

4 个答案:

答案 0 :(得分:6)

编辑:Remus是正确的,这只会在查询计划首次点击缓存而不是后续运行时显示已编译的版本。

您应该能够从查询计划中获取参数,因为它包含最后使用的参数。改变你的代码:

select * 
from sys.dm_exec_requests r 
cross apply sys.dm_exec_query_plan(plan_handle) as qp
cross apply sys.dm_exec_sql_text(r.sql_handle) 
where r.database_id = DB_ID('<dbname>') 

您会发现查询计划的最后一列是query_plan,您可以手动检查的查询计划的xml版本,XML的底部是参数,或者如果您喜欢挑战,请使用XML解析和XQuery拉出ParameterList标签

答案 1 :(得分:2)

一个查询,它提供登录名,执行时间和查询作为最后一个事件的文本,如果可以帮助您连接sys.dm_exec_query_stats,但是可以使用

SELECT distinct
s.login_name,
qs.creation_time 
,SUBSTRING(st.text, (qs.statement_start_offset/2) + 1,
((CASE statement_end_offset
  WHEN -1 THEN DATALENGTH(st.text)
  ELSE qs.statement_end_offset END
  - qs.statement_start_offset)/2) + 1) AS statement_text
FROM sys.dm_exec_sessions S
LEFT JOIN sys.dm_exec_connections AS c ON S.session_id = c.session_id
,sys.dm_exec_query_stats QS --qs on c.most_recent_sql_handle = qs.sql_handle
OUTER APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
WHERE ST.text LIKE '%yourKeyWord%' and s.login_name <> 'NT SERVICE\SQLSERVERAGENT'
order by qs.creation_time desc

答案 2 :(得分:1)

万一有人偶然发现此线程以寻找适当的解决方案(其他人遗憾地缺乏此解决方案),我发现了这个helpful post from mssqltips

我整理了一下查询语句并进行了一些调整,以使其成为一个:

-- cleanup
IF OBJECT_ID('tempdb..#compiledValue') IS NOT NULL
    DROP TABLE #compiledValue
GO

-- Prepare temp table #compiledValue
SELECT  
    OBJECT_NAME(est.objectid) ObjectName,
    DB_NAME(est.dbid) DBName,
    eqs.last_execution_time,
    est.text,
    (eqs.statement_start_offset / 2) + 1 AS statement_start_offset,
    (IIF(eqs.statement_end_offset = -1, DATALENGTH(est.text), eqs.statement_end_offset) - eqs.statement_start_offset) / 2 + 1 AS statement_end_offset,
    TRY_CONVERT(XML, 
        SUBSTRING(etqp.query_plan,
            CHARINDEX('<ParameterList>',etqp.query_plan),
            CHARINDEX('</ParameterList>',etqp.query_plan) + LEN('</ParameterList>') - CHARINDEX('<ParameterList>',etqp.query_plan) )) AS statement_params
INTO #compiledValue
FROM sys.dm_exec_query_stats eqs
     CROSS APPLY sys.dm_exec_sql_text(eqs.sql_handle) est
     CROSS APPLY sys.dm_exec_text_query_plan(eqs.plan_handle, eqs.statement_start_offset, eqs.statement_end_offset) etqp

SELECT 
    cvalue.last_execution_time,
    cvalue.DBName,
    cvalue.ObjectName,
    SUBSTRING(cvalue.text,cvalue.statement_start_offset,cvalue.statement_end_offset) AS sql_text,
    pc.compiled.value('@Column', 'nvarchar(128)') AS Parameterlist,
    pc.compiled.value('@ParameterCompiledValue', 'nvarchar(128)') AS [compiled Value]
FROM #compiledValue cvalue
OUTER APPLY cvalue.statement_params.nodes('//ParameterList/ColumnReference') AS pc(compiled)
WHERE cvalue.text NOT LIKE '%#compiledValue%' -- ignore these queries based on temp table name
ORDER BY cvalue.last_execution_time DESC
GO

-- cleanup
DROP TABLE #compiledValue
GO

效果很好,每个参数都有自己的一行。

例如: Screen capture from MS SQL Server Management Studio of the result

答案 3 :(得分:0)

如果您使用的是不存在 TRY_CONVERT 函数的 SQL Server 2012 或 Amazon RDS 之前的版本,则这是可以工作的 Indigo 查询的变体。

-- cleanup
IF OBJECT_ID('tempdb..#compiledValue') IS NOT NULL
    DROP TABLE #compiledValue
GO

-- Prepare temp table #compiledValue
SELECT  
    OBJECT_NAME(est.objectid) ObjectName,
    DB_NAME(est.dbid) DBName,
    eqs.last_execution_time,
    est.text,
    (eqs.statement_start_offset / 2) + 1 AS statement_start_offset,
    (IIF(eqs.statement_end_offset = -1, DATALENGTH(est.text), eqs.statement_end_offset) - eqs.statement_start_offset) / 2 + 1 AS statement_end_offset,
    --TRY_CONVERT(XML, 
    --    SUBSTRING(etqp.query_plan,
    --        CHARINDEX('<ParameterList>',etqp.query_plan),
    --        CHARINDEX('</ParameterList>',etqp.query_plan) + LEN('</ParameterList>') - CHARINDEX('<ParameterList>',etqp.query_plan) )) AS statement_params,
    CASE
        WHEN CHARINDEX('<ParameterList>', etqp.query_plan) > 0
            THEN CONVERT(XML, 
                    SUBSTRING(etqp.query_plan, 
                        CHARINDEX('<ParameterList>', etqp.query_plan), 
                        CHARINDEX('</ParameterList>', etqp.query_plan) + LEN('</ParameterList>') - CHARINDEX('<ParameterList>', etqp.query_plan) )) 
        ELSE NULL
    END AS statement_params
INTO #compiledValue
FROM sys.dm_exec_query_stats eqs
     CROSS APPLY sys.dm_exec_sql_text(eqs.sql_handle) est
     CROSS APPLY sys.dm_exec_text_query_plan(eqs.plan_handle, eqs.statement_start_offset, eqs.statement_end_offset) etqp

SELECT 
    cvalue.last_execution_time,
    cvalue.DBName,
    cvalue.ObjectName,
    SUBSTRING(cvalue.text,cvalue.statement_start_offset,cvalue.statement_end_offset) AS sql_text,
    pc.compiled.value('@Column', 'nvarchar(128)') AS Parameterlist,
    pc.compiled.value('@ParameterCompiledValue', 'nvarchar(128)') AS [compiled Value]
FROM #compiledValue cvalue
OUTER APPLY cvalue.statement_params.nodes('//ParameterList/ColumnReference') AS pc(compiled)
WHERE cvalue.text NOT LIKE '%#compiledValue%' -- ignore these queries based on temp table name
ORDER BY cvalue.last_execution_time DESC
GO

-- cleanup
DROP TABLE #compiledValue
GO