SQL Server中查存储过程依赖应组合使用sys.dm_exec_describe_first_result_set_for_object和sys.sql_expression_dependencies,并辅以OBJECT_DEFINITION字符串扫描及手动验证,因动态SQL、加密对象、跨库引用等场景下单一视图不可靠。

查不到存储过程依赖关系?先确认 sys.dm_exec_describe_first_result_set 不能用
SQL Server 的 sys.dm_exec_describe_first_result_set 看起来能推断依赖,但它只分析语句首结果集,对 EXEC 动态拼接、IF 分支里调用的存储过程完全不识别。真正稳定可用的是 sys.dm_exec_describe_first_result_set_for_object(仅限 SQL Server 2012+)和更底层的 sys.sql_expression_dependencies。
sys.sql_expression_dependencies 返回空?检查对象作用域和状态
这个视图只记录「显式引用」,且要求被引用对象在创建时存在、未被重命名或删除。常见空结果原因:
-
CREATE PROC中用EXEC('...')调用另一个存储过程 → 不被记录 - 被引用的表/视图/存储过程在创建当前过程时尚未创建 → 依赖列为
NULL,is_ambiguous = 1 - 当前存储过程是用
WITH ENCRYPTION创建的 → 视图无法解析内容,返回空行或不完整 - 查询时没加
WHERE referencing_id = OBJECT_ID('your_proc_name')→ 默认查全部,容易漏看
动态 SQL 里的依赖怎么抓?得靠字符串扫描 + 手动验证
没有自动方案能 100% 解析 EXEC(@sql) 或 sp_executesql 里的对象名。可行做法是:
- 用
sys.dm_exec_describe_first_result_set_for_object先查静态部分依赖 - 对
OBJECT_DEFINITION(OBJECT_ID('proc_name'))结果做字符串匹配:EXEC\s+\[?(\w+)\]?、INSERT\s+INTO\s+\[?(\w+)\]?等正则模式(注意转义和大小写) - 把匹配出的名字批量用
OBJECT_ID(name)验证是否存在,排除拼写错误或临时表 - 特别留意
tempdb..#t这类本地临时表 —— 它们不会出现在sys.sql_expression_dependencies里,但运行时确实构成依赖
跨数据库依赖显示为 NULL?改用三段式名称 + 检查 USE 上下文
如果存储过程里写了 OtherDB.dbo.TableA,sys.sql_expression_dependencies 的 referenced_database_name 字段可能为 NULL,不是 bug,是设计如此。原因:
- SQL Server 在解析时默认以当前数据库为上下文,不主动跨库解析
- 必须确保查询时连接的数据库就是该存储过程所属库(比如过程在
DB1,就用USE DB1后再查依赖) - 若仍为
NULL,可手动补全:从referenced_entity_name提取对象名,结合referenced_schema_name,再用SELECT DB_NAME(database_id)反查实际所在库(需配合sys.dm_exec_cached_plans和sys.dm_exec_sql_text)
依赖分析最麻烦的从来不是查不到,而是查到的“看起来有”但实际运行时根本没走那条路径,或者查不到的“看似没有”却在动态 SQL 里悄悄执行。别信单个视图的结果,组合用、交叉验、手动翻定义,才是常态。










