SQLServer 查看依赖关系
13. 查看数据库对象间的依赖关系在SQL Server中,(可编程)对象间的引用即依赖关系,有多种方式可以检查,随着版本变更,方式也有所不同。 父子关系的对象,不通过依赖关系来查询,比如: 1. 外键关系 use tempdb GO --drop table tb1,tb2 create table tb1 ( col1 int Primary key,col2 int ) insert into tb1 values (2,2),(3,0)">4,0)">5,0)">2) table tb2 ( col3 primary constraint FK_tb2 foreign key references tb1(col1) ) 检查外键 select object_name(constraint_object_id) constraint_name,object_name(parent_object_id) parent_object_name,255)">col_name(parent_object_id,parent_column_id) parent_object_column_name,255)">object_name(referenced_object_id) referenced_object_name,255)">col_name(referenced_object_id,referenced_column_id) referenced_object_column_name from sys.foreign_key_columns where referenced_object_id = object_id('tb1') 2. 表上的索引,触发器 if OBJECT_ID(T',U') is not null drop table T table T(id int) GO if exists(select 1 from sys.indexes where name IX_001' and object_id ')) index T.IX_001 index IX_001 on T(id) OBJECT_ID (test_dml_triggerTRnull trigger test_dml_trigger ON T AFTER INSERT,UPDATE AS RAISERROR (Notify Customer Relations16,0)">10); 检查索引 object_name(object_id) as table_name,128)">* from sys.indexes ') 检查DML触发器 select name object_name(a.parent_obj) as dml_trigger_name from sysobjects a where a.xtype ' ? 在SSMS中,数据库对象上右击/View Dependencies,可以查看到对象的依赖关系,那么用脚本怎么检查? database DB1; database DB2; use DB1 T1table T1 table T1(id int); V1Vview V1 as * from T1 SP1Pproc SP1 as from V1 use DB2 SP2proc SP2 from DB1..V1 SP3proc SP3 exec DB2..SP2 test_schema.T2table test_schema.T2 from sys.schemas where name test_schema') schema test_schema table test_schema.T2(c1 int,c2 SP4proc SP4 from test_schema.T2 GO ? 一. SQL Server 2000依赖关系查询 从SQL Server 2000沿用下来的系统表,SQL Server 2016仍适用,后续版本将不再支持 USE DB1 SELECT o.name,o.xtype,p.name as referenced_name,p.xtype FROM sysdepends d INNER JOIN sysobjects o ON d.id = o.id JOIN sysobjects p ON d.depid = p.id 从SQL Server 2000沿用下来的存储过程,SQL Server 2016仍适用,后续版本将不再支持 exec sp_depends ' 无文档记载的sp_MS存储过程,只能检查被自己引用的对象,SQL Server 2016仍适用 exec sp_MSdependencies ' 注意:sysdepends,sp_depends,sp_MSdependencies 只能检查当前数据库对象的引用/被引用,对于跨数据库对象依赖关系,无法检查。 ? 二. SQL Server 2005依赖关系查询 从SQL Server 2005沿用下来的系统视图,SQL Server 2016仍适用,后续版本将不再支持 FROM sys.sql_dependencies d JOIN sys.objects o ON d.= o.object_id JOIN sys.objects p ON d.referenced_major_id = p.object_id注意:和sysdepends,sp_depends一样,sys.sql_dependencies只能检查当前数据库对象的引用/被引用,对于跨数据库对象依赖关系,无法检查。 ? 三. SQL Server 2008后依赖关系查询 从SQL Server 2008开始用的系统视图 FROM sys.sql_expression_dependencies d ON d.referencing_id ON d.referenced_id object_id 从SQL Server 2008开始用的系统函数,引用我的对象 SELECT FROM sys.dm_sql_referencing_entities(dbo.V1OBJECT') 从SQL Server 2008开始用的系统函数,被我引用的对象 FROM sys.dm_sql_referenced_entities(dbo.SP1USE DB2 dbo.SP2')注意: (1) sys.sql_expression_dependencies及这两个新增函数,都可以检查当前数据库中跨数据库,跨服务器引用的对象,但当前数据库对象被跨数据库,跨服务器引用,无法检查; (2) 新增的2个系统函数,可以更方便的检查引用和被引用,但对象名要完整,必须包含schema name,否则无法返回正确结果; (3) sys.dm_sql_referenced_entities 还可以查看被数据库/服务器DDL触发器引用的对象; FROM sys.dm_sql_referenced_entities (ddl_database_trigger_nameDATABASE_DDL_TRIGGER'); (4) sys.dm_sql_referencing_entities 还可以查看引用了类型/分区函数等的对象。 ? 四.?无法查明的依赖关系 1.?跨数据库/服务器对象 上面提到从SQL Server 2008开始,跨数据库,跨服务器引用的对象,已经可以查询; 但是写法上要稍微调整下,因为当前数据库中,并没有其他数据库对象的object_id,所以不能按照object_id来关联。改动后脚本如下: SELECT schema_name(o.schema_id) as schema_name,o.name as object_name,d.referenced_server_name,d.referenced_database_name,255)">isnull(d.referenced_schema_name,0)">dboas referenced_schema_name,d.referenced_entity_name object_id注意:跨数据库/跨服务器对象的引用,仅能检查3部分/4部分名称格式的对象引用,即如:server_name.db_name.schema_name.object_name格式,对于OPENROWSET,OPENQUERY,OPENDATASOURCE的引用并不记录。 ? 2.?临时对象 对于存储过程中用到的临时表,只能检查到create table创建的非#开头临时表,并且用函数检查还会报错,因为表事先并不存在。 SP5proc SP5 into #temp from sys.objects into _getdate() table #t (id into #t 100 _tproc _t table _t (id into _t 100 GO ? 3.?动态SQL里引用的对象 T2table T2 table T2(id SP6proc SP6 exec(select * from T1declare @SQL nvarchar(max) set @SQL = Nselect * from T2' exec sp_executesql @SQL exec (@SQL) 无论系统视图/函数,都查不到 dbo.SP6'); 动态SQL里引用的对象,无论系统视图/函数,都查不到;也许只能试试查可编程对象的文本定义: ANSI SQL标准里定义的INFORMATION_SCHEMA对象 from INFORMATION_SCHEMA.ROUTINES where ROUTINE_DEFINITION like %T2%SQL Server 2000沿用下来的可编程对象文本定义 from syscomments where text SQL Server 2005开始的可编程对象文本定义 from sys.sql_modules where definition '? 注意:这种方法,对于hard coding的对象名,非常好用,但是, (1) 有时动态SQL里的对象名称并不是hard coding,所以也不一定能找到;比如: EXEC(SELECT * FROM dbo.table+ _name') SELECT * FROM + @table)(2) 另外一些书写不严格的SQL,也无法定位到对象名,比如: FROM dbo . table_name 这语法竟然也能通过 FROM dbo.table_name_2 名字只是部分类似,table_name_2不是table_name? 4.?延迟名称解析 如果被引用的数据库对象,在后面创建,那么用2000或者2005的方式去检查,会出现延迟名称解析(deferred name resolution),用2008后的方式,已经没有这个问题。 T3table T3 table T3(id 引用的SP_1st后创建 SP_2ndproc SP_2nd exec SP_1st SP_1stproc SP_1st from T3 出现延迟名称解析(deferred name resolution): 存储过程SP_2nd的引用对象,无法获取到 刷新对象定义,可以解决 exec sp_refreshsqlmodule 如果是视图,也可以这样刷新 exec sp_refreshview view_name使用2008后的系统视图,没有这个问题,它同时保存了引用对象的名称,object_id可先置为NULL object_id 注意:新的视图虽然解决了延迟名称解析的问题,但也带来了新问题,如果引用的对象一直未被创建,或者创建后被重名命/删除,这条依赖关系仍然存在。 ? 五.?如何获取多层嵌套引用的对象 有时一个对象下会多层嵌套引用数据库对象,尤其是视图/存储过程等的嵌套调用,在某些场景下获取所有嵌套调用的对象很有用,比如:要更新某个存储过程下所有引用到的表上的统计信息。 table dbo.table2(c2 proc dbo.sp12 from table2 table dbo.table1(c1 view dbo.view1 from dbo.table1 view dbo.view2 from dbo.view1 proc dbo.sp11 from dbo.view2 proc dbo.sp13 exec dbo.sp11 exec DB2.dbo.sp12 @entity_name varchar(512) @entity_name dbo.sp13' ;with tmp as ( * WHERE d.referencing_id object_id(@entity_name) union all SELECT d.JOIN tmp t ON t.referenced_id = d.referencing_id ) select * from tmp FROM tmp d object_id LEFT JOIN sys.objects ro ON d.referenced_id = ro.object_id WHERE ro.type_desc = 'USER_TABLE' or ro.type_desc is null 注意: (1) 最后注释的几行脚本,限制用来获取所有被引用到的表,可根据需要调整; (2) 跨数据库/服务器引用的对象,如果不是最后一层,还得切换到对应的数据库/服务器再运行此脚本。 ? 小结: 1.?查看被哪些对象引用,sys.sql_expression_dependencies,sys.dm_sql_referencing_entities, sys.sql_modules,无论哪种方式都查不到被跨数据库引用; 2.?查看引用了哪些对象,sys.sql_expression_dependencies,sys.dm_sql_referenced_entities,都可以查到跨数据库引用的对象,如果查看嵌套调用的对象,还是递归查询sys.sql_expression_dependencies比较直接。 源文:http://www.cnblogs.com/seusoftware/p/4858115.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Centos 7.2中MongoDB数据库的安装与卸载教程
- MDF文件在SQL Server中的恢复技术
- 判断字段是否被更新 新旧数据写入Audit Log表中
- SQL查询中的MS Access VBA数据类型不匹配错误
- sql-server – 标量函数fn_cdc_get_min_lsn()不断返回’0x0
- sql – 如何使用LAMBDA表达式在LINQ中进行IN或CONTAINS?
- sql-server – SqlServer中autoincremental int主键的最大值
- SqlServer和Oracle从多行记录(数据集)中查询结果并拼接成
- sql – 如何在DB2中使用LIKE和IN?
- sqlserver 2005的安装