You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

SQL Server 2008中如何查询指定存储过程调用的内部存储过程列表

嘿,在SQL Server 2008里要揪出指定存储过程调用的所有内部存储过程(包括嵌套调用的那些),我给你整理了两个靠谱的方案,都是用系统自带的视图/函数实现的,不用额外工具:

方案1:系统视图 + 递归CTE(支持多层嵌套)

这个方法能遍历所有层级的调用关系,哪怕被调用的存储过程又调用了其他过程,也能一网打尽。关键是用递归CTE来逐层挖掘依赖,还加了循环引用的防护,避免无限递归。

直接用下面的代码,记得替换掉@ProcName@SchemaName为你实际的存储过程名和架构(比如默认的dbo):

DECLARE @ProcName NVARCHAR(128) = 'YourTargetProcedure'; -- 替换成你的存储过程名
DECLARE @SchemaName NVARCHAR(128) = 'dbo'; -- 替换成对应的架构名

WITH ProcDependencies AS (
    -- 第一层:目标存储过程直接调用的存储过程
    SELECT 
        referenced_schema_name AS SchemaName,
        referenced_entity_name AS ProcName,
        1 AS Level
    FROM sys.sql_expression_dependencies sed
    JOIN sys.sql_modules sm ON sed.referencing_id = sm.object_id
    JOIN sys.objects o ON sm.object_id = o.object_id
    WHERE 
        o.name = @ProcName 
        AND o.schema_id = SCHEMA_ID(@SchemaName)
        AND sed.referenced_entity_name IS NOT NULL
        AND sed.referenced_class_desc = 'OBJECT'
        -- 只筛选存储过程类型的依赖
        AND OBJECTPROPERTY(OBJECT_ID(sed.referenced_schema_name + '.' + sed.referenced_entity_name), 'IsProcedure') = 1

    UNION ALL

    -- 递归层:被调用的存储过程再调用的其他存储过程
    SELECT 
        sed.referenced_schema_name AS SchemaName,
        sed.referenced_entity_name AS ProcName,
        pd.Level + 1 AS Level
    FROM sys.sql_expression_dependencies sed
    JOIN ProcDependencies pd ON sed.referencing_id = OBJECT_ID(pd.SchemaName + '.' + pd.ProcName)
    WHERE 
        sed.referenced_entity_name IS NOT NULL
        AND sed.referenced_class_desc = 'OBJECT'
        AND OBJECTPROPERTY(OBJECT_ID(sed.referenced_schema_name + '.' + sed.referenced_entity_name), 'IsProcedure') = 1
        -- 防止循环引用导致无限递归(比如ProcA调用ProcB,ProcB又调用ProcA)
        AND NOT EXISTS (
            SELECT 1 FROM ProcDependencies pd2 
            WHERE pd2.SchemaName = sed.referenced_schema_name 
            AND pd2.ProcName = sed.referenced_entity_name
        )
)
-- 去重后输出,按层级排序
SELECT DISTINCT SchemaName, ProcName, Level
FROM ProcDependencies
ORDER BY Level, SchemaName, ProcName;
方案2:用sys.dm_sql_referenced_entities函数

这个系统函数专门用来返回指定对象引用的所有实体,用法更简洁。同样结合递归CTE处理嵌套调用:

DECLARE @ProcFullName NVARCHAR(256) = 'dbo.YourTargetProcedure'; -- 替换成你的存储过程全名(架构+名称)

WITH RecursiveReferences AS (
    -- 初始层:直接调用的存储过程
    SELECT 
        referenced_schema_name AS SchemaName,
        referenced_entity_name AS ProcName,
        1 AS Level
    FROM sys.dm_sql_referenced_entities(@ProcFullName, 'OBJECT')
    WHERE referenced_class_desc = 'OBJECT'
        AND OBJECTPROPERTY(OBJECT_ID(referenced_schema_name + '.' + referenced_entity_name), 'IsProcedure') = 1

    UNION ALL

    -- 递归层:嵌套调用的存储过程
    SELECT 
        r.referenced_schema_name AS SchemaName,
        r.referenced_entity_name AS ProcName,
        rr.Level + 1 AS Level
    FROM sys.dm_sql_referenced_entities(rr.SchemaName + '.' + rr.ProcName, 'OBJECT') r
    JOIN RecursiveReferences rr ON 1=1
    WHERE r.referenced_class_desc = 'OBJECT'
        AND OBJECTPROPERTY(OBJECT_ID(r.referenced_schema_name + '.' + r.referenced_entity_name), 'IsProcedure') = 1
        AND NOT EXISTS (
            SELECT 1 FROM RecursiveReferences rr2 
            WHERE rr2.SchemaName = r.referenced_schema_name 
            AND rr2.ProcName = r.referenced_entity_name
        )
)
SELECT DISTINCT SchemaName, ProcName, Level
FROM RecursiveReferences
ORDER BY Level, SchemaName, ProcName;
一些重要提醒
  • 权限:你需要有VIEW DEFINITION权限才能访问这些系统视图和函数,不然会报错。
  • 动态SQL限制:如果存储过程里用了动态SQL调用其他过程(比如EXEC('dbo.ProcA')),这两种方法都抓不到——因为动态SQL的依赖是运行时才确定的,静态分析没法识别。这种情况得自己解析存储过程的定义文本做字符串匹配,但准确性会打折扣。
  • 循环引用:代码里已经加了判断来避免无限递归,如果你的环境里有互相调用的存储过程,不用担心会卡死。

内容的提问来源于stack exchange,提问作者CSK

火山引擎 最新活动