查依赖返回空或不全,主因是对象创建时依赖未存在、用动态SQL、上下文错误、加密或权限不足;需结合系统视图、字符串扫描与手动验证。
sys.sql_expression_dependencies 返回空,不等于没依赖,大概率是对象创建时依赖尚未存在、用了动态 SQL 或当前数据库上下文不对。这个视图只记录「显式、静态、可解析」的引用,且要求被引用对象在 CREATE PROC 时已存在并可被解析。
USE 存储过程所在数据库,否则 referenced_database_name 可能为 NULL 或错乱WITH ENCRYPTION —— 加密后该视图无法读取内容,直接返回空行is_ambiguous = 1 表示名字冲突或权限不足,比如同名表在多个 schema 下,或你没有 VIEW DEFINITION 权限sys.sql_expression_dependencies,它漏掉动态部分;搭配 sys.dm_exec_describe_first_result_set_for_object(SQL Server 2012+)一起用EXEC(@sql) 或 sp_executesql 里的对象名,SQL Server 在编译期完全不解析,所有依赖分析工具都无视它。这不是 bug,是设计使然。
OBJECT_DEFINITION(OBJECT_ID('proc_name')) 拿到完整文本,再做正则匹配:EXECs+[?(w+)]?、INSERTs+INTOs+[?(w+)]?、FROMs+[?(w+)]?
OBJECT_ID(name),排除拼写错误、临时表(如 #temp)、表变量(@table)——它们不会出现在任何依赖视图里,但运行时真会报错tempdb..#t 这种三段式写法:虽然写了库名,但 tempdb 是运行时上下文,sys.sql_expression_dependencies 从不记录如果存储过程里写了 OtherDB.dbo.TableA,sys.sql_expression_dependencies.referenced_database_name 很可能还是 NULL。这不是缺陷,是 SQL Server 解析器的行为:它以当前会话的默认数据库为上下文,不主动跨库 resolve 名字。
DB1,就 USE DB1 再查)NULL,可人工补全:referenced_entity_name + referenced_schema_name 拼出完整对象名,再用 DB_NAME() 和 SCHEMA_NAME() 验证是否存在dbo.TableA),这种写法在跨库场景下极易导致部署后运行时报 Invalid object name
当存储过程先建、依赖对象后建(比如先建 usp_A 再建 usp_B),SQL Server 不会自动补全依赖关系,sp_depends 和系统视图都查不到。这不是缓存问题,是元数据未生成。
sys.sp_refreshsqlmodule 'dbo.usp_A' 强制重解析,它会重新扫描定义体、更新 sys.sql_expression_dependencies
EXEC sys.sp_refreshsqlmodule 对每个 type = 'P' 的 sys.objects 执行一遍(注意不要在高负载时段跑)EXEC('...') 或对象名拼接 —— 这类依赖永远无法被自动捕获,只能靠字符串扫描