sys.sql_expression_dependencies常返回空,因其仅记录显式、静态、创建时存在的引用;动态SQL、对象后建、WITH ENCRYPTION加密、未指定schema等均导致缺失。

查 sys.sql_expression_dependencies 为什么经常返回空
这个视图是 SQL Server 官方推荐的依赖查询入口,但它只捕获「显式、静态、创建时存在」的引用。常见失效场景包括:
• EXEC('EXEC usp_do_something') 这类动态拼接调用,不会被记录
• 被引用的对象(比如表或另一个存储过程)在创建当前过程时尚未存在,is_ambiguous 字段会是 1,referenced_id 为 NULL
• 存储过程用了 WITH ENCRYPTION,视图无法解析内容,结果为空或不完整
• 没指定 schema,比如查 'usp_log' 却漏了 'dbo.usp_log',实际依赖可能落在其他 schema 下
必须人工核对 SQL Agent 作业和 NOEXEC 执行结果
自动化工具扫不到硬编码调用,但 SQL Agent 是高频盲区。别只看 job 名字,要查 msdb.dbo.sysjobsteps.command 字段是否含目标过程名——大小写、空格、换行都可能藏匿调用痕迹。
另外,SET NOEXEC ON 后执行该过程,能暴露两类关键问题:
• 报 Invalid object name:说明它依赖的对象已删或改名,大概率废弃
• 报 Invalid column name 或参数不匹配:说明下游调用逻辑已变更,过程本身可能还在用,但已不可靠
这两步不跑,光看元数据就删,等于闭眼拆引信。
跨库引用容易被 sys.sql_modules 搜索漏掉
用 CHARINDEX 在 sys.sql_modules.definition 里搜过程名,看似直接,但有三个坑:
• 不加 QUOTENAME 会导致子串误匹配,比如搜 'usp_log' 会把 'usp_login_history' 也抓进来
• 只查当前库,而实际调用可能来自其他数据库的 EXEC otherdb.dbo.usp_xxx
• 忽略大小写敏感实例:若数据库排序规则是 Latin1_General_CS_AS,CHARINDEX 默认区分大小写,得显式加 COLLATE DATABASE_DEFAULT
建议用 sys.dm_exec_cached_plans + sys.dm_exec_sql_text 扫缓存,比纯文本搜索更贴近真实执行路径。
Oracle 的 DROP PROCEDURE ... FORCE 不解决依赖判断
Oracle 的 FORCE 选项只是跳过依赖检查强行删,不是帮你确认“能不能删”。真正要判断依赖,得查 ALL_DEPENDENCIES 视图:
• SELECT name, type, referenced_name, referenced_type FROM ALL_DEPENDENCIES WHERE referenced_name = 'YOUR_PROCEDURE_NAME' AND referenced_owner = 'YOUR_SCHEMA'
• 注意 type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE', 'VIEW'),别只盯存储过程
• 如果查不到,不代表没依赖——可能是调用方用了同义词(Synonym)或动态 SQL,仍需结合应用日志和代码扫描

















