如何在SQL Server(SSMS)中追踪所有对象依赖关系
SQL Server表与视图全关联追踪解决方案
一、基础依赖查询:系统视图组合
先利用sys.sql_expression_dependencies配合系统对象视图,覆盖绝大多数常规依赖(含跨库/跨服务器),这是静态分析的基础。
示例查询:
SELECT -- 依赖方信息 OBJECT_SCHEMA_NAME(d.referencing_id) AS referencing_schema, OBJECT_NAME(d.referencing_id) AS referencing_object, o1.type_desc AS referencing_object_type, -- 被依赖方信息 d.referenced_server_name, d.referenced_database_name, d.referenced_schema_name, d.referenced_entity_name, o2.type_desc AS referenced_object_type FROM sys.sql_expression_dependencies d JOIN sys.objects o1 ON d.referencing_id = o1.object_id LEFT JOIN sys.objects o2 ON d.referenced_id = o2.object_id AND d.referenced_database_name IS NULL -- 仅匹配当前库对象 WHERE -- 筛选目标对象类型:表(U)、视图(V) o1.type IN ('U', 'V') AND (d.referenced_entity_name IS NOT NULL) ORDER BY referencing_schema, referencing_object;
注意:这个视图无法捕获动态SQL拼接的依赖、临时表/表变量的依赖,以及部分隐式引用。
二、扩展分析:依赖解析函数
用sys.dm_sql_referenced_entities和sys.dm_sql_referencing_entities函数,能更精准解析单个对象的依赖,甚至能识别部分静态字符串形式的动态SQL引用。
1. 追踪单个对象的被依赖项
SELECT referenced_server_name, referenced_database_name, referenced_schema_name, referenced_entity_name, referenced_minor_name, is_caller_dependent FROM sys.dm_sql_referenced_entities('dbo.YourViewName', 'OBJECT');
2. 批量遍历所有对象
可以用游标或CTE循环遍历所有表和视图,批量收集依赖:
DECLARE @schemaName NVARCHAR(128), @objectName NVARCHAR(128); DECLARE objCursor CURSOR FOR SELECT OBJECT_SCHEMA_NAME(object_id), OBJECT_NAME(object_id) FROM sys.objects WHERE type IN ('U', 'V'); OPEN objCursor; FETCH NEXT FROM objCursor INTO @schemaName, @objectName; WHILE @@FETCH_STATUS = 0 BEGIN SELECT @schemaName AS referencing_schema, @objectName AS referencing_object, referenced_server_name, referenced_database_name, referenced_schema_name, referenced_entity_name FROM sys.dm_sql_referenced_entities(QUOTENAME(@schemaName) + '.' + QUOTENAME(@objectName), 'OBJECT'); FETCH NEXT FROM objCursor INTO @schemaName, @objectName; END; CLOSE objCursor; DEALLOCATE objCursor;
三、模拟SSMS依赖分析:解析对象定义文本
SSMS的依赖视图会结合系统信息和对象定义的文本解析,对于系统视图漏抓的情况,可以直接解析sys.sql_modules中的对象定义:
- 提取定义中的表/视图引用,比如用字符串匹配识别
[schema].[table]或db.schema.table格式的引用:
SELECT OBJECT_SCHEMA_NAME(m.object_id) AS obj_schema, OBJECT_NAME(m.object_id) AS obj_name, o.type_desc AS obj_type, -- 这里用简单的字符串匹配示例,可根据实际情况优化正则 SUBSTRING(m.definition, PATINDEX('%[[a-z0-9_]].[a-z0-9_]%', m.definition), 100) AS possible_reference FROM sys.sql_modules m JOIN sys.objects o ON m.object_id = o.object_id WHERE o.type IN ('U', 'V') AND PATINDEX('%[[a-z0-9_]].[a-z0-9_]%', m.definition) > 0;
提示:这种方法可能会误识别别名或注释中的内容,建议结合系统视图的结果交叉验证,也可以用CLR函数实现更精准的SQL语法解析。
四、特殊场景处理
- 动态SQL拼接:如果是
EXEC('SELECT * FROM ' + @tableName)这类动态SQL,静态分析无法捕获,只能通过运行时追踪(比如Extended Events监控sql_statement_completed事件)来记录实际调用的对象。 - 临时表/表变量:这类对象属于会话级,静态分析只能识别定义中的声明,无法追踪实际关联,只能通过代码评审或运行时分析补充。
内容的提问来源于stack exchange,提问作者Omar Gherardi
相关产品推荐
相关产品推荐

