检索跨多个数据库运行存储过程的名称

时间:2011-02-25 01:11:57

标签: sql sql-server stored-procedures dynamic-management-views

我正在尝试编写一个报告当前数据库活动的查询。该查询将各种DMV链接在一起,如sys.dm_exec_connectionssys.dm_exec_sessionssys.dm_exec_requests等。该查询还会通过sys.dm_exec_sql_text函数提取实际查询。

(我知道Activity Monitor和SQL Profiler。我需要在查询中收集这些信息,因此这些程序都不相关。)

我们系统中的大部分活动都是在存储过程和函数中进行的。在这个查询中看到这些过程的名称会很高兴。

我的问题是:

如何可靠地显示正在执行的存储过程或函数的名称?

我知道sys.dm_exec_sql_text函数返回objectid,我可以将此objectid加入sys.objects。问题是,此服务器上有多个数据库,sys.objects仅适用于当前数据库。我希望此查询能够显示正在运行的对象名称,无论该查询恰好在哪个数据库上运行。

到目前为止,我唯一的解决方案是使用sp_msforeachdb创建一个包含所有数据库中所有对象ID和名称的临时表,并从dm_exec_sql_text函数的结果中加入到该表中。 / p>

临时表方法有更好的解决方案吗?我觉得我错过了什么。

2 个答案:

答案 0 :(得分:3)

我会推荐Adam Machanic的优秀sp_WhoISActive。它不会返回确切的对象名称,但会返回以可点击的形式执行的sql命令。

答案 1 :(得分:1)

- 我使用以下过程:

USE [master]
GO

CREATE PROC [dbo].[sp_who3] 
AS

    SET NOCOUNT ON 

    DECLARE @LoginName varchar(128)
    DECLARE @AppName varchar(128)

    SELECT [SPID] = s.[spid]
        , [CPU] = s.[cpu]
        , [Physical_IO] = s.[physical_io]
        , [Blocked] = s.[blocked]
        , [LoginName] = CONVERT([sysname], RTRIM(s.[Loginame]))
        , [Database] = d.[name]
        , [AppName] = s.[program_name]
        , [HostName] = s.[hostname]
        , [Status] = s.[Status]
        , [Cmd] = s.[cmd]
        , [Last Batch] = s.[last_batch]
        , [Kill Command] = 'Kill ' + CAST(s.[spid] AS varchar(10))
        , [Buffer Command] = 'DBCC InputBuffer(' + CAST(s.[spid] AS varchar(10)) 
                                                         + ')'
    FROM [master].[dbo].[sysprocesses] s WITH(NOLOCK)
    JOIN [master].[sys].[databases] d WITH(NOLOCK)
                ON s.[dbid] = d.[database_id]
    WHERE s.[Status]  'background'
        AND s.[spid]  @@SPID  --@CurrentSpid@
    ORDER BY s.[blocked] DESC, s.[physical_io] DESC, s.[cpu] DESC, CONVERT([sysname], RTRIM(s.[Loginame]))

    BEGIN
        SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

        SELECT [Spid] = er.[session_Id]
        , [ECID] = sp.[ECID]
        , [Database] = DB_NAME(sp.[dbid])
        , [User] = [nt_username]
        , [Status] = er.[status]
        , [Wait] = [wait_type]
        , [Individual Query] = SUBSTRING(qt.[text], er.[statement_start_offset] / 2, (CASE WHEN er.[statement_end_offset] = - 1 THEN LEN(CONVERT(VARCHAR(MAX), qt.[text])) * 2
                            ELSE er.[statement_end_offset] END - er.[statement_start_offset]) / 2)
        , [Parent Query] = qt.[text]
        , [Program] = sp.[program_name]
        , [Hostname] = sp.[Hostname]
        , [Domain] = sp.[nt_domain]
        , [Start_time] = er.[Start_time]
        FROM [sys].[dm_exec_requests] er WITH(NOLOCK)
        INNER JOIN [sys].[sysprocesses] sp WITH(NOLOCK)
                ON er.[session_id] = sp.[spid]
        CROSS APPLY [sys].[dm_exec_sql_text](er.[sql_handle]) qt 
        WHERE er.[session_Id] > 50                      -- Ignore system spids.
            AND er.[session_Id] NOT IN (@@SPID)     -- Ignore the current statement.
        ORDER BY er.[session_Id], sp.[ECID]
    END
GO