/* Author: Konstantin Taranov Source: https://github.com/ktaranov/sqlserver-kit/blob/master/Scripts/Find_Object_Dependecy.sql */ DECLARE @objectName SYSNAME = 'ObjectName'; DECLARE @schemaName SYSNAME = 'SchemaName'; IF Object_id('tempdb..#tempdep', 'U') IS NOT NULL DROP TABLE #tempdep; IF Object_id('tempdb..#t1', 'U') IS NOT NULL DROP TABLE #t1; IF Object_id('tempdb..#t2', 'U') IS NOT NULL DROP TABLE #t2; CREATE TABLE #tempdep ( objid INT NOT NULL ,objname SYSNAME NOT NULL ,objschema SYSNAME NULL ,objdb SYSNAME NOT NULL ,objtype SMALLINT NOT NULL ); EXEC sp_executesql N'INSERT INTO #tempdep SELECT tbl.object_id AS [ID], tbl.name AS [Name], SCHEMA_NAME(tbl.schema_id) AS [Schema], db_name(), 3 FROM sys.tables AS tbl WHERE (tbl.name=@_msparam_0 and SCHEMA_NAME(tbl.schema_id)=@_msparam_1)', N'@_msparam_0 nvarchar(4000),@_msparam_1 nvarchar(4000)', @_msparam_0=@objectName, @_msparam_1=@schemaName; DECLARE @find_referencing_objects INT; SET @find_referencing_objects = 1; -- parameters: -- 1. create table #tempdep (objid int NOT NULL, objtype smallint NOT NULL) -- contains source objects -- 2. @find_referencing_objects defines ordering -- 1 order for drop -- 0 order for script DECLARE @must_set_nocount_off BIT; SET @must_set_nocount_off = 0; IF @@OPTIONS & 512 = 0 SET @must_set_nocount_off = 1; SET nocount ON; DECLARE @u INT; DECLARE @udf INT; DECLARE @v INT; DECLARE @sp INT; DECLARE @def INT; DECLARE @rule INT; DECLARE @tr INT; DECLARE @uda INT; DECLARE @uddt INT; DECLARE @xml INT; DECLARE @udt INT; DECLARE @assm INT; DECLARE @part_sch INT; DECLARE @part_func INT; DECLARE @synonym INT; DECLARE @sequence INT; DECLARE @udtt INT; DECLARE @ddltr INT; DECLARE @unknown INT; DECLARE @pg INT; SET @u = 3; SET @udf = 0; SET @v = 2; SET @sp = 4; SET @def = 6; SET @rule = 7; SET @tr = 8; SET @uda = 11; SET @synonym = 12; SET @sequence = 13; -- above 100 -> not in sys.objects SET @uddt = 101; SET @xml = 102; SET @udt = 103; SET @assm = 1000; SET @part_sch = 201; SET @part_func = 202; SET @udtt = 104; SET @ddltr = 203; SET @unknown = 1001; SET @pg = 204; -- variables for referenced type obtained from sys.sql_expression_dependencies DECLARE @obj INT; SET @obj = 20; DECLARE @type INT; SET @type = 21; -- variables for xml and part_func are already there CREATE TABLE #t1 ( object_id INT NULL ,object_name SYSNAME COLLATE database_default NULL ,object_schema SYSNAME COLLATE database_default NULL ,object_db SYSNAME NULL ,object_svr SYSNAME NULL ,object_type SMALLINT NOT NULL ,relative_id INT NOT NULL ,relative_name SYSNAME COLLATE database_default NOT NULL ,relative_schema SYSNAME COLLATE database_default NULL ,relative_db SYSNAME NULL ,relative_svr SYSNAME NULL ,relative_type SMALLINT NOT NULL ,schema_bound BIT NOT NULL ,rank SMALLINT NULL ,degree INT NULL ); -- we need to create another temporary table to store the dependencies from sys.sql_expression_dependencies till the updated values are inserted finally into #t1 CREATE TABLE #t2 ( object_id INT NULL ,object_name SYSNAME COLLATE database_default NULL ,object_schema SYSNAME COLLATE database_default NULL ,object_db SYSNAME NULL ,object_svr SYSNAME NULL ,object_type SMALLINT NOT NULL ,relative_id INT NOT NULL ,relative_name SYSNAME COLLATE database_default NOT NULL ,relative_schema SYSNAME COLLATE database_default NULL ,relative_db SYSNAME NULL ,relative_svr SYSNAME NULL ,relative_type SMALLINT NOT NULL ,schema_bound BIT NOT NULL ,rank SMALLINT NULL ); -- This index will ensure that we have unique parent-child relationship CREATE UNIQUE CLUSTERED INDEX i1 ON #t1(object_name, object_schema, object_db, object_svr, object_type, relative_name, relative_schema, relative_type) WITH ignore_dup_key; DECLARE @iter_no INT; SET @iter_no = 1; DECLARE @rows INT; SET @rows = 1; INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT l.objid ,l.objname ,l.objschema ,l.objdb ,l.objtype ,l.objid ,l.objname ,l.objschema ,l.objdb ,l.objtype ,1 ,@iter_no FROM #tempdep l; -- change the object_id of table types to their user_defined_id UPDATE #t1 SET object_id = tt.user_type_id ,relative_id = tt.user_type_id FROM sys.table_types AS tt WHERE tt.type_table_object_id = #t1.object_id AND object_type = @udtt; WHILE @rows > 0 BEGIN SET @rows = 0 IF ( 1 = @find_referencing_objects ) BEGIN -- HARD DEPENDENCIES -- these dependencies have to be in the same database only -- tables that reference uddts or udts INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT tbl.object_id ,tbl.name ,Schema_name(tbl.schema_id) ,t.object_db ,@u ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.columns AS c ON c.user_type_id = t.object_id JOIN sys.tables AS tbl ON tbl.object_id = c.object_id WHERE @iter_no = t.rank AND ( t.object_type = @uddt OR t.object_type = @udt ) AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- udtts that reference uddts or udts INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT tt.user_type_id ,tt.name ,Schema_name(tt.schema_id) ,t.object_db ,@udtt ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.columns AS c ON c.user_type_id = t.object_id JOIN sys.table_types AS tt ON tt.type_table_object_id = c.object_id WHERE @iter_no = t.rank AND ( t.object_type = @uddt OR t.object_type = @udt ) AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- tables/views that reference triggers INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT o.object_id ,o.name ,Schema_name(o.schema_id) ,t.object_db ,@tr ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.objects AS o ON o.parent_object_id = t.object_id AND o.type = 'TR' WHERE @iter_no = t.rank AND ( t.object_type = @u OR t.object_type = @v ) AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- tables that reference defaults (only default objects) INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT o.object_id ,o.name ,Schema_name(o.schema_id) ,t.object_db ,@u ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.columns AS clmns ON clmns.default_object_id = t.object_id JOIN sys.objects AS o ON o.object_id = clmns.object_id AND 0 = ISNULL(o.parent_object_id, 0) WHERE @iter_no = t.rank AND t.object_type = @def AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- types that reference defaults (only default objects) INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT tp.user_type_id ,tp.name ,Schema_name(tp.schema_id) ,t.object_db ,@uddt ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.types AS tp ON tp.default_object_id = t.object_id JOIN sys.objects AS o ON o.object_id = t.object_id AND 0 = ISNULL(o.parent_object_id, 0) WHERE @iter_no = t.rank AND t.object_type = @def AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- tables that reference rules INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT tbl.object_id ,tbl.name ,Schema_name(tbl.schema_id) ,t.object_db ,@u ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.columns AS clmns ON clmns.rule_object_id = t.object_id JOIN sys.tables AS tbl ON tbl.object_id = clmns.object_id WHERE @iter_no = t.rank AND t.relative_type = @rule AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- types that reference rules INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT tp.user_type_id ,tp.name ,Schema_name(tp.schema_id) ,t.object_db ,@uddt ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.types AS tp ON tp.rule_object_id = t.object_id WHERE @iter_no = t.rank AND t.object_type = @rule AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- tables that reference XmlSchemaCollections INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT tbl.object_id ,tbl.name ,Schema_name(tbl.schema_id) ,t.object_db ,@u ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.columns AS c ON c.xml_collection_id = t.object_id JOIN sys.tables AS tbl ON tbl.object_id = c.object_id -- eliminate views WHERE @iter_no = t.rank AND t.object_type = @xml AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- table types that reference XmlSchemaCollections INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT tt.user_type_id ,tt.name ,Schema_name(tt.schema_id) ,t.object_db ,@udtt ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.columns AS c ON c.xml_collection_id = t.object_id JOIN sys.table_types AS tt ON tt.type_table_object_id = c.object_id WHERE @iter_no = t.rank AND t.object_type = @xml AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- procedures that reference XmlSchemaCollections INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT o.object_id ,o.name ,Schema_name(o.schema_id) ,t.object_db ,( CASE WHEN o.type IN ( 'P', 'RF', 'PC' ) THEN @sp ELSE @udf END ) ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.parameters AS c ON c.xml_collection_id = t.object_id JOIN sys.objects AS o ON o.object_id = c.object_id WHERE @iter_no = t.rank AND t.object_type = @xml AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- udf, sp, uda, trigger all that reference assembly INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT o.object_id ,o.name ,Schema_name(o.schema_id) ,t.object_db ,( CASE o.type WHEN 'AF' THEN @uda WHEN 'PC' THEN @sp WHEN 'FS' THEN @udf WHEN 'FT' THEN @udf WHEN 'TA' THEN @tr ELSE @udf END ) ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.assembly_modules AS am ON ( ( am.assembly_id = t.object_id ) AND ( am.assembly_id >= 65536 ) ) JOIN sys.objects AS o ON am.object_id = o.object_id WHERE @iter_no = t.rank AND t.object_type = @assm AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- udt that reference assembly INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT at.user_type_id ,at.name ,Schema_name(at.schema_id) ,t.object_db ,@udt ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.assembly_types AS at ON ( ( at.assembly_id = t.object_id ) AND ( at.is_user_defined = 1 ) ) WHERE @iter_no = t.rank AND t.object_type = @assm AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- assembly that reference assembly INSERT #t1 (object_id ,object_name ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT asm.assembly_id ,asm.name ,t.object_db ,@assm ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.assembly_references AS ar ON ( ( ar.referenced_assembly_id = t.object_id ) AND ( ar.referenced_assembly_id >= 65536 ) ) JOIN sys.assemblies AS asm ON asm.assembly_id = ar.assembly_id WHERE @iter_no = t.rank AND t.object_type = @assm AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- table references table INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT tbl.object_id ,tbl.name ,Schema_name(tbl.schema_id) ,t.object_db ,@u ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.foreign_keys AS fk ON fk.referenced_object_id = t.object_id JOIN sys.tables AS tbl ON tbl.object_id = fk.parent_object_id WHERE @iter_no = t.rank AND t.object_type = @u AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- uda references types INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT o.object_id ,o.name ,Schema_name(o.schema_id) ,t.object_db ,@uda ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.parameters AS p ON p.user_type_id = t.object_id JOIN sys.objects AS o ON o.object_id = p.object_id AND o.type = 'AF' WHERE @iter_no = t.rank AND t.object_type IN ( @udt, @uddt, @udtt ) AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); -- table,view references partition scheme INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT o.object_id ,o.name ,Schema_name(o.schema_id) ,t.object_db ,( CASE o.type WHEN 'V' THEN @v ELSE @u END ) ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.indexes AS idx ON idx.data_space_id = t.object_id JOIN sys.objects AS o ON o.object_id = idx.object_id WHERE @iter_no = t.rank AND t.object_type = @part_sch AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- partition scheme references partition function INSERT #t1 (object_id ,object_name ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT ps.data_space_id ,ps.name ,t.object_db ,@part_sch ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.partition_schemes AS ps ON ps.function_id = t.object_id WHERE @iter_no = t.rank AND t.object_type = @part_func AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- plan guide references sp, udf, triggers INSERT #t1 (object_id ,object_name ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT pg.plan_guide_id ,pg.name ,t.object_db ,@pg ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.plan_guides AS pg ON pg.scope_object_id = t.object_id WHERE @iter_no = t.rank AND t.object_type IN ( @sp, @udf, @tr ) AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- synonym refrences object INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT s.object_id ,s.name ,Schema_name(s.schema_id) ,t.object_db ,@synonym ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,0 ,@iter_no + 1 FROM #t1 AS t JOIN sys.synonyms AS s ON Object_id(s.base_object_name) = t.object_id WHERE @iter_no = t.rank AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- sequences that reference uddts INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT s.object_id ,s.name ,Schema_name(s.schema_id) ,t.object_db ,@sequence ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,0 ,@iter_no + 1 FROM #t1 AS t JOIN sys.sequences AS s ON s.user_type_id = t.object_id WHERE @iter_no = t.rank AND ( t.object_type = @uddt ) AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- SOFT DEPENDENCIES DECLARE name_cursor CURSOR FOR SELECT DISTINCT t.object_id ,t.object_name ,t.object_schema ,t.object_type FROM #t1 AS t WHERE @iter_no = t.rank AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ) AND t.object_type NOT IN ( @part_sch, @assm, @tr, @ddltr ); OPEN name_cursor; DECLARE @objid INT; DECLARE @objname SYSNAME; DECLARE @objschema SYSNAME; DECLARE @objtype SMALLINT; DECLARE @fullname SYSNAME; DECLARE @objecttype SYSNAME; FETCH next FROM name_cursor INTO @objid, @objname, @objschema, @objtype; WHILE ( @@FETCH_STATUS <> -1 ) BEGIN SET @fullname = CASE WHEN @objschema IS NULL THEN QUOTENAME(@objname) ELSE QUOTENAME(@objschema) + '.' + QUOTENAME(@objname) END; SET @objecttype = CASE WHEN @objtype IN ( @uddt, @udt, @udtt ) THEN 'TYPE' WHEN @objtype = @xml THEN 'XML_SCHEMA_COLLECTION' WHEN @objtype = @part_func THEN 'PARTITION_FUNCTION' ELSE 'OBJECT' END; INSERT #t2 (object_type ,object_id ,object_name ,object_schema ,object_db ,object_svr ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT CASE dep.referencing_class WHEN 1 THEN (SELECT CASE WHEN obj.type = 'U' THEN @u WHEN obj.type = 'V' THEN @v WHEN obj.type = 'TR' THEN @tr WHEN obj.type IN ( 'P', 'RF', 'PC' ) THEN @sp WHEN obj.type IN ( 'AF' ) THEN @uda WHEN obj.type IN ( 'TF', 'FN', 'IF', 'FS', 'FT' ) THEN @udf WHEN obj.type = 'D' THEN @def WHEN obj.type = 'SN' THEN @synonym WHEN obj.type = 'SO' THEN @sequence ELSE @obj END FROM sys.objects AS obj WHERE obj.object_id = dep.referencing_id) WHEN 6 THEN (SELECT CASE WHEN ( tp.is_assembly_type = 1 ) THEN @udt WHEN ( tp.is_table_type = 1 ) THEN @udtt ELSE @uddt END FROM sys.types AS tp WHERE tp.user_type_id = dep.referencing_id) WHEN 7 THEN @u WHEN 9 THEN @u WHEN 10 THEN @xml WHEN 12 THEN @ddltr WHEN 21 THEN @part_func END ,dep.referencing_id ,dep.referencing_entity_name ,dep.referencing_schema_name ,DB_NAME() ,NULL ,@objid ,@objname ,@objschema ,DB_NAME() ,@objtype ,0 ,@iter_no + 1 FROM sys.dm_sql_referencing_entities(@fullname, @objecttype) AS dep; FETCH NEXT FROM name_cursor INTO @objid, @objname, @objschema, @objtype; END CLOSE name_cursor; DEALLOCATE name_cursor; UPDATE #t2 SET object_id = obj.object_id ,object_name = obj.name ,object_schema = Schema_name(obj.schema_id) ,object_type = CASE WHEN obj.type = 'U' THEN @u WHEN obj.type = 'V' THEN @v END FROM sys.objects AS o JOIN sys.objects AS obj ON obj.object_id = o.parent_object_id WHERE o.object_id = #t2.object_id AND ( #t2.object_type = @obj OR o.parent_object_id != 0 ) AND #t2.rank = @iter_no + 1; INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_svr ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_svr ,relative_type ,schema_bound ,rank) SELECT object_id ,object_name ,object_schema ,object_db ,object_svr ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_svr ,relative_type ,schema_bound ,rank FROM #t2 WHERE @iter_no + 1 = rank AND #t2.object_id != #t2.relative_id; SET @rows = @rows + @@rowcount; END ELSE BEGIN -- SOFT DEPENDENCIES -- insert all values from sys.sql_expression_dependencies for the corresponding object -- first insert them in #t2, update them and THEN finally insert them in #t1 INSERT #t2 (object_type ,object_name ,object_schema ,object_db ,object_svr ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT CASE dep.referenced_class WHEN 1 THEN @obj WHEN 6 THEN @type WHEN 7 THEN @u WHEN 9 THEN @u WHEN 10 THEN @xml WHEN 21 THEN @part_func END ,dep.referenced_entity_name ,dep.referenced_schema_name ,dep.referenced_database_name ,dep.referenced_server_name ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,dep.is_schema_bound_reference ,@iter_no + 1 FROM #t1 AS t JOIN sys.sql_expression_dependencies AS dep ON dep.referencing_id = t.object_id WHERE @iter_no = t.rank AND t.object_svr IS NULL AND t.object_db = DB_NAME(); -- insert all the dependency values in case of a table that references a check INSERT #t2 (object_type ,object_name ,object_schema ,object_db ,object_svr ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT CASE dep.referenced_class WHEN 1 THEN @obj WHEN 6 THEN @type WHEN 7 THEN @u WHEN 9 THEN @u WHEN 10 THEN @xml WHEN 21 THEN @part_func END ,dep.referenced_entity_name ,dep.referenced_schema_name ,dep.referenced_database_name ,dep.referenced_server_name ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,dep.is_schema_bound_reference ,@iter_no + 1 FROM #t1 AS t JOIN sys.sql_expression_dependencies AS d ON d.referenced_id = t.object_id JOIN sys.objects AS o ON o.object_id = d.referencing_id AND o.type = 'C' JOIN sys.sql_expression_dependencies AS dep ON dep.referencing_id = d.referencing_id AND dep.referenced_id != t.object_id WHERE @iter_no = t.rank AND t.object_svr IS NULL AND t.object_db = DB_NAME() AND t.object_type = @u; -- insert all the dependency values in case of an object that belongs to another object whose dependencies are being found INSERT #t2 (object_type ,object_name ,object_schema ,object_db ,object_svr ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT CASE dep.referenced_class WHEN 1 THEN @obj WHEN 6 THEN @type WHEN 7 THEN @u WHEN 9 THEN @u WHEN 10 THEN @xml WHEN 21 THEN @part_func END ,dep.referenced_entity_name ,dep.referenced_schema_name ,dep.referenced_database_name ,dep.referenced_server_name ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,dep.is_schema_bound_reference ,@iter_no + 1 FROM #t1 AS t JOIN sys.objects AS o ON o.parent_object_id = t.object_id JOIN sys.sql_expression_dependencies AS dep ON dep.referencing_id = o.object_id WHERE @iter_no = t.rank AND t.object_svr IS NULL AND t.object_db = DB_NAME(); -- queries for objects with object_id null and object_svr null - resolve them -- we will build the query to resolve the objects -- increase @rows as we bind the objects DECLARE db_cursor CURSOR FOR SELECT DISTINCT ISNULL(object_db, DB_NAME()) FROM #t2 AS t WHERE t.rank = ( @iter_no + 1 ) AND t.object_id IS NULL AND t.object_svr IS NULL; OPEN db_cursor; DECLARE @dbname SYSNAME; DECLARE @quote_quoted_dbname SYSNAME; DECLARE @bracket_quoted_dbname SYSNAME; FETCH next FROM db_cursor INTO @dbname; WHILE ( @@FETCH_STATUS <> -1 ) BEGIN IF ( DB_ID(@dbname) IS NULL ) BEGIN FETCH next FROM db_cursor INTO @dbname; CONTINUE; END SET @quote_quoted_dbname = QUOTENAME(@dbname, ''''); SET @bracket_quoted_dbname = QUOTENAME(@dbname, ']'); DECLARE @query NVARCHAR(max); -- WHEN schema is not null -- @obj SET @query = 'UPDATE #t2 set object_db = N' + @quote_quoted_dbname + ', object_id = obj.object_id, object_type = case WHEN obj.type = ''U'' THEN ' + CAST(@u AS NVARCHAR(8)) + ' WHEN obj.type = ''V'' THEN ' + CAST(@v AS NVARCHAR(8)) + ' WHEN obj.type = ''TR'' THEN ' + CAST(@tr AS NVARCHAR(8)) + ' WHEN obj.type in ( ''P'', ''RF'', ''PC'' ) THEN ' + CAST(@sp AS NVARCHAR(8)) + ' WHEN obj.type in ( ''AF'' ) THEN ' + CAST(@uda AS NVARCHAR(8)) + ' WHEN obj.type in ( ''TF'', ''FN'', ''IF'', ''FS'', ''FT'' ) THEN ' + CAST(@udf AS NVARCHAR(8)) + ' WHEN obj.type = ''D'' THEN ' + CAST(@def AS NVARCHAR(8)) + ' WHEN obj.type = ''SN'' THEN ' + CAST(@synonym AS NVARCHAR(8)) + ' WHEN obj.type = ''SO'' THEN ' + CAST(@sequence AS NVARCHAR(8)) + ' ELSE ' + CAST(@unknown AS NVARCHAR(8)) + ' END FROM ' + @bracket_quoted_dbname + '.sys.objects as obj JOIN ' + @bracket_quoted_dbname + '.sys.schemas as sch on sch.schema_id = obj.schema_id WHERE obj.name = #t2.object_name collate database_default AND sch.name = #t2.object_schema collate database_default AND #t2.object_type = ' + CAST(@obj AS NVARCHAR(8)) + ' AND #t2.object_schema IS NOT NULL AND (#t2.object_db IS NULL or #t2.object_db = N' + @quote_quoted_dbname + ') AND #t2.rank = (' + CAST(@iter_no AS NVARCHAR(8)) + '+1) AND #t2.object_id IS NULL and #t2.object_svr IS NULL;' EXEC sp_executesql @query; -- @type SET @query = 'update #t2 set object_db = N' + @quote_quoted_dbname + ', object_id = t.user_type_id, object_type = case WHEN t.is_assembly_type = 1 THEN ' + CAST(@udt AS NVARCHAR(8)) + ' WHEN t.is_table_type = 1 THEN ' + CAST(@udtt AS NVARCHAR(8)) + ' ELSE ' + CAST(@uddt AS NVARCHAR(8)) + ' END FROM ' + @bracket_quoted_dbname + '.sys.types AS t JOIN ' + @bracket_quoted_dbname + '.sys.schemas as sch on sch.schema_id = t.schema_id WHERE t.name = #t2.object_name collate database_default AND sch.name = #t2.object_schema collate database_default AND #t2.object_type = ' + CAST(@type AS NVARCHAR(8)) + ' and #t2.object_schema IS NOT NULL AND (#t2.object_db IS NULL or #t2.object_db = N' + @quote_quoted_dbname + ') AND #t2.rank = (' + CAST(@iter_no AS NVARCHAR(8)) + '+1) AND #t2.object_id IS NULL and #t2.object_svr IS NULL;'; EXEC sp_executesql @query; -- @xml SET @query = 'UPDATE #t2 set object_db = N' + @quote_quoted_dbname + ', object_id = x.xml_collection_id FROM ' + @bracket_quoted_dbname + '.sys.xml_schema_collections AS x JOIN ' + @bracket_quoted_dbname + '.sys.schemas as sch on sch.schema_id = x.schema_id WHERE x.name = #t2.object_name collate database_default AND sch.name = #t2.object_schema collate database_default AND #t2.object_type = ' + CAST(@xml AS NVARCHAR(8)) + ' AND #t2.object_schema IS NOT NULL AND (#t2.object_db IS NULL OR #t2.object_db = N' + @quote_quoted_dbname + ') AND #t2.rank = (' + CAST(@iter_no AS NVARCHAR(8)) + '+1) AND #t2.object_id IS NULL and #t2.object_svr IS NULL;'; EXEC sp_executesql @query; -- @part_func - schema is always null -- @schema is null -- consider schema as 'dbo' -- @obj SET @query = 'UPDATE #t2 set object_db = N' + @quote_quoted_dbname + ', object_id = obj.object_id, object_schema = SCHEMA_NAME(obj.schema_id), object_type = CASE WHEN obj.type = ''U'' THEN ' + CAST(@u AS NVARCHAR(8)) + ' WHEN obj.type = ''V'' THEN ' + CAST(@v AS NVARCHAR(8)) + ' WHEN obj.type = ''TR'' THEN ' + CAST(@tr AS NVARCHAR(8)) + ' WHEN obj.type in ( ''P'', ''RF'', ''PC'' ) THEN ' + CAST(@sp AS NVARCHAR(8)) + ' WHEN obj.type in ( ''AF'' ) THEN ' + CAST(@uda AS NVARCHAR(8)) + ' WHEN obj.type in ( ''TF'', ''FN'', ''IF'', ''FS'', ''FT'' ) THEN ' + CAST(@udf AS NVARCHAR(8)) + ' WHEN obj.type = ''D'' THEN ' + CAST(@def AS NVARCHAR(8)) + ' WHEN obj.type = ''SN'' THEN ' + CAST(@synonym AS NVARCHAR(8)) + ' WHEN obj.type = ''SO'' THEN ' + CAST(@sequence AS NVARCHAR(8)) + ' ELSE ' + CAST(@unknown AS NVARCHAR(8)) + ' END FROM ' + @bracket_quoted_dbname + '.sys.objects as obj WHERE obj.name = #t2.object_name collate database_default AND SCHEMA_NAME(obj.schema_id) = ''dbo'' AND #t2.object_type = ' + CAST(@obj AS NVARCHAR(8)) + ' AND #t2.object_schema IS NULL AND (#t2.object_db IS NULL OR #t2.object_db = N' + @quote_quoted_dbname + ') AND #t2.rank = (' + CAST(@iter_no AS NVARCHAR(8)) + '+1) AND #t2.object_id IS NULL and #t2.object_svr IS NULL;'; EXEC sp_executesql @query; -- @type SET @query = 'update #t2 set object_db = N' + @quote_quoted_dbname + ', object_id = t.user_type_id, object_schema = SCHEMA_NAME(t.schema_id), object_type = case WHEN t.is_assembly_type = 1 THEN ' + CAST(@udt AS NVARCHAR(8)) + ' WHEN t.is_table_type = 1 THEN ' + CAST(@udtt AS NVARCHAR(8)) + ' else ' + CAST(@uddt AS NVARCHAR(8)) + ' end from ' + @bracket_quoted_dbname + '.sys.types AS t where t.name = #t2.object_name collate database_default AND SCHEMA_NAME(t.schema_id) = ''dbo'' AND #t2.object_type = ' + CAST(@type AS NVARCHAR(8)) + ' and #t2.object_schema IS NULL AND (#t2.object_db IS NULL OR #t2.object_db = N' + @quote_quoted_dbname + ') AND #t2.rank = (' + CAST(@iter_no AS NVARCHAR(8)) + '+1) AND #t2.object_id IS NULL AND #t2.object_svr IS NULL;'; EXEC sp_executesql @query; -- @xml SET @query = 'update #t2 set object_db = N' + @quote_quoted_dbname + ', object_id = x.xml_collection_id, object_schema = SCHEMA_NAME(x.schema_id) FROM ' + @bracket_quoted_dbname + '.sys.xml_schema_collections as x WHERE x.name = #t2.object_name collate database_default AND SCHEMA_NAME(x.schema_id) = ''dbo'' AND #t2.object_type = ' + CAST(@xml AS NVARCHAR(8)) + ' AND #t2.object_schema IS NULL AND (#t2.object_db IS NULL OR #t2.object_db = N' + @quote_quoted_dbname + ') and #t2.rank = (' + CAST(@iter_no AS NVARCHAR(8)) + '+1) and #t2.object_id IS NULL and #t2.object_svr IS NULL;'; EXEC sp_executesql @query; -- consider schema as t.relative_schema -- the parent object will have the default schema of user in case of dynamic schema binding -- @obj SET @query = 'UPDATE #t2 set object_db = N' + @quote_quoted_dbname + ', object_id = obj.object_id, object_schema = SCHEMA_NAME(obj.schema_id), object_type = CASE WHEN obj.type = ''U'' THEN ' + CAST(@u AS NVARCHAR(8)) + ' WHEN obj.type = ''V'' THEN ' + CAST(@v AS NVARCHAR(8)) + ' WHEN obj.type = ''TR'' THEN ' + CAST(@tr AS NVARCHAR(8)) + ' WHEN obj.type in ( ''P'', ''RF'', ''PC'' ) THEN ' + CAST(@sp AS NVARCHAR(8)) + ' WHEN obj.type in ( ''AF'' ) THEN ' + CAST(@uda AS NVARCHAR(8)) + ' WHEN obj.type in ( ''TF'', ''FN'', ''IF'', ''FS'', ''FT'' ) THEN ' + CAST(@udf AS NVARCHAR(8)) + ' WHEN obj.type = ''D'' THEN ' + CAST(@def AS NVARCHAR(8)) + ' WHEN obj.type = ''SN'' THEN ' + CAST(@synonym AS NVARCHAR(8)) + ' WHEN obj.type = ''SO'' THEN ' + CAST(@sequence AS NVARCHAR(8)) + ' else ' + CAST(@unknown AS NVARCHAR(8)) + ' end from ' + @bracket_quoted_dbname + '.sys.objects as obj JOIN ' + @bracket_quoted_dbname + '.sys.schemas as sch on sch.schema_id = obj.schema_id WHERE obj.name = #t2.object_name collate database_default AND sch.name = #t2.relative_schema collate database_default AND #t2.object_type = ' + CAST(@obj AS NVARCHAR(8)) + ' AND #t2.object_schema IS NULL AND (#t2.object_db IS NULL or #t2.object_db = N' + @quote_quoted_dbname + ') AND #t2.rank = (' + CAST(@iter_no AS NVARCHAR(8)) + '+1) AND #t2.object_id IS NULL AND #t2.object_svr IS NULL;'; EXEC sp_executesql @query; -- @type SET @query = 'UPDATE #t2 set object_db = N' + @quote_quoted_dbname + ', object_id = t.user_type_id, object_schema = SCHEMA_NAME(t.schema_id), object_type = case WHEN t.is_assembly_type = 1 THEN ' + CAST(@udt AS NVARCHAR(8)) + ' WHEN t.is_table_type = 1 THEN ' + CAST(@udtt AS NVARCHAR(8)) + ' else ' + CAST(@uddt AS NVARCHAR(8)) + ' END FROM ' + @bracket_quoted_dbname + '.sys.types as t JOIN ' + @bracket_quoted_dbname + '.sys.schemas as sch on sch.schema_id = t.schema_id WHERE t.name = #t2.object_name collate database_default AND sch.name = #t2.relative_schema collate database_default AND #t2.object_type = ' + CAST(@type AS NVARCHAR(8)) + ' and #t2.object_schema IS NULL AND (#t2.object_db IS NULL or #t2.object_db = N' + @quote_quoted_dbname + ') AND #t2.rank = (' + CAST(@iter_no AS NVARCHAR(8)) + '+1) AND #t2.object_id IS NULL AND #t2.object_svr IS NULL;' EXEC sp_executesql @query; -- @xml SET @query = 'UPDATE #t2 set object_db = N' + @quote_quoted_dbname + ', object_id = x.xml_collection_id, object_schema = SCHEMA_NAME(x.schema_id) FROM ' + @bracket_quoted_dbname + '.sys.xml_schema_collections as x JOIN ' + @bracket_quoted_dbname + '.sys.schemas as sch on sch.schema_id = x.schema_id WHERE x.name = #t2.object_name collate database_default AND sch.name = #t2.relative_schema collate database_default AND #t2.object_type = ' + CAST(@xml AS NVARCHAR(8)) + ' AND #t2.object_schema IS NULL AND (#t2.object_db IS NULL or #t2.object_db = N' + @quote_quoted_dbname + ') AND #t2.rank = (' + CAST(@iter_no AS NVARCHAR(8)) + '+1) and #t2.object_id IS NULL AND #t2.object_svr IS NULL;'; EXEC sp_executesql @query; -- @part_func always have schema as null SET @query = 'update #t2 set object_db = N' + @quote_quoted_dbname + ', object_id = p.function_id FROM ' + @bracket_quoted_dbname + '.sys.partition_functions as p WHERE p.name = #t2.object_name collate database_default AND #t2.object_type = ' + CAST(@part_func AS NVARCHAR(8)) + ' and (#t2.object_db IS NULL or #t2.object_db = N' + @quote_quoted_dbname + ') and #t2.rank = (' + CAST(@iter_no AS NVARCHAR(8)) + '+1) AND #t2.object_id IS NULL and #t2.object_svr IS NULL'; EXEC sp_executesql @query; -- update the shared object if any (schema is not null) UPDATE #t2 SET object_db = 'master' ,object_id = o.object_id ,object_type = @sp FROM master.sys.objects AS o JOIN master.sys.schemas AS sch ON sch.schema_id = o.schema_id WHERE o.name = #t2.object_name COLLATE database_default AND sch.name = #t2.object_schema COLLATE database_default AND o.type IN ( 'P', 'RF', 'PC' ) AND #t2.object_id IS NULL AND #t2.object_name LIKE 'sp/_%' ESCAPE '/' AND #t2.object_db IS NULL AND #t2.object_svr IS NULL; -- update the shared object if any (schema is null) UPDATE #t2 SET object_db = 'master' ,object_id = o.object_id ,object_schema = Schema_name(o.schema_id) ,object_type = @sp FROM master.sys.objects AS o WHERE o.name = #t2.object_name COLLATE database_default AND Schema_name(o.schema_id) = 'dbo' COLLATE database_default AND o.type IN ( 'P', 'RF', 'PC' ) AND #t2.object_schema IS NULL AND #t2.object_id IS NULL AND #t2.object_name LIKE 'sp/_%' ESCAPE '/' AND #t2.object_db IS NULL AND #t2.object_svr IS NULL; FETCH next FROM db_cursor INTO @dbname; END; CLOSE db_cursor; DEALLOCATE db_cursor; UPDATE #t2 SET object_type = @unknown WHERE object_id IS NULL; INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_svr ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_svr ,relative_type ,schema_bound ,rank) SELECT object_id ,object_name ,object_schema ,object_db ,object_svr ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_svr ,relative_type ,schema_bound ,rank FROM #t2 WHERE @iter_no + 1 = rank; SET @rows = @rows + @@rowcount; -- HARD DEPENDENCIES -- uddt or udt referenced by table INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT tp.user_type_id ,tp.name ,Schema_name(tp.schema_id) ,t.object_db ,CASE tp.is_assembly_type WHEN 1 THEN @udt ELSE @uddt END ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.columns AS col ON col.object_id = t.object_id JOIN sys.types AS tp ON tp.user_type_id = col.user_type_id AND tp.schema_id != 4 WHERE @iter_no = t.rank AND t.object_type = @u AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- uddt or udt referenced by table type INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT tp.user_type_id ,tp.name ,Schema_name(tp.schema_id) ,t.object_db ,CASE tp.is_assembly_type WHEN 1 THEN @udt ELSE @uddt END ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.table_types AS tt ON tt.user_type_id = t.object_id JOIN sys.columns AS col ON col.object_id = tt.type_table_object_id JOIN sys.types AS tp ON tp.user_type_id = col.user_type_id AND tp.schema_id != 4 WHERE @iter_no = t.rank AND t.object_type = @udtt AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- table or view referenced by trigger INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT o.object_id ,o.name ,Schema_name(o.schema_id) ,t.object_db ,CASE o.type WHEN 'V' THEN @v ELSE @u END ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.triggers AS tr ON tr.object_id = t.object_id JOIN sys.objects AS o ON o.object_id = tr.parent_id WHERE @iter_no = t.rank AND t.object_type = @tr AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- defaults (only default objects) referenced by tables INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT o.object_id ,o.name ,Schema_name(o.schema_id) ,t.object_db ,@def ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.columns AS clmns ON clmns.object_id = t.object_id JOIN sys.objects AS o ON o.object_id = clmns.default_object_id AND 0 = ISNULL(o.parent_object_id, 0) WHERE @iter_no = t.rank AND t.object_type = @u AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- defaults (only default objects) referenced by types INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT o.object_id ,o.name ,Schema_name(o.schema_id) ,t.object_db ,@def ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.types AS tp ON tp.user_type_id = t.object_id JOIN sys.objects AS o ON o.object_id = tp.default_object_id AND 0 = ISNULL(o.parent_object_id, 0) WHERE @iter_no = t.rank AND t.object_type = @uddt AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- rules referenced by tables INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT o.object_id ,o.name ,Schema_name(o.schema_id) ,t.object_db ,@rule ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.columns AS clmns ON clmns.object_id = t.object_id JOIN sys.objects AS o ON o.object_id = clmns.rule_object_id AND 0 = ISNULL(o.parent_object_id, 0) WHERE @iter_no = t.rank AND t.relative_type = @u AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- rules referenced by types INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT o.object_id ,o.name ,Schema_name(o.schema_id) ,t.object_db ,@rule ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.types AS tp ON tp.user_type_id = t.object_id JOIN sys.objects AS o ON o.object_id = tp.rule_object_id AND 0 = ISNULL(o.parent_object_id, 0) WHERE @iter_no = t.rank AND t.relative_type = @uddt AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- XmlSchemaCollections referenced by tables INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT x.xml_collection_id ,x.name ,Schema_name(x.schema_id) ,t.object_db ,@xml ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.columns AS c ON c.object_id = t.object_id JOIN sys.xml_schema_collections AS x ON x.xml_collection_id = c.xml_collection_id AND x.schema_id != 4 WHERE @iter_no = t.rank AND t.object_type = @u AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- XmlSchemaCollections referenced by tabletypes INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT x.xml_collection_id ,x.name ,Schema_name(x.schema_id) ,t.object_db ,@xml ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.table_types AS tt ON tt.user_type_id = t.object_id JOIN sys.columns AS c ON c.object_id = tt.type_table_object_id JOIN sys.xml_schema_collections AS x ON x.xml_collection_id = c.xml_collection_id AND x.schema_id != 4 WHERE @iter_no = t.rank AND t.object_type = @udtt AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- XmlSchemaCollections referenced by procedures INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT x.xml_collection_id ,x.name ,Schema_name(x.schema_id) ,t.object_db ,@xml ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.parameters AS c ON c.object_id = t.object_id JOIN sys.xml_schema_collections AS x ON x.xml_collection_id = c.xml_collection_id AND x.schema_id != 4 WHERE @iter_no = t.rank AND t.object_type IN ( @sp, @udf ) AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- table referenced by table INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT tbl.object_id ,tbl.name ,Schema_name(tbl.schema_id) ,t.object_db ,@u ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.foreign_keys AS fk ON fk.parent_object_id = t.object_id JOIN sys.tables AS tbl ON tbl.object_id = fk.referenced_object_id WHERE @iter_no = t.rank AND t.object_type = @u AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- uddts referenced by uda INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT tp.user_type_id ,tp.name ,Schema_name(tp.schema_id) ,t.object_db ,CASE WHEN tp.is_table_type = 1 THEN @udtt WHEN tp.is_assembly_type = 1 THEN @udt ELSE @uddt END ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.parameters AS p ON p.object_id = t.object_id JOIN sys.types AS tp ON tp.user_type_id = p.user_type_id WHERE @iter_no = t.rank AND t.object_type = @uda AND t.object_type = @uda AND tp.user_type_id > 256; SET @rows = @rows + @@rowcount; -- assembly referenced by assembly INSERT #t1 (object_id ,object_name ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT asm.assembly_id ,asm.name ,t.object_db ,@assm ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.assembly_references AS ar ON ( ( ar.assembly_id = t.object_id ) AND ( ar.referenced_assembly_id >= 65536 ) ) JOIN sys.assemblies AS asm ON asm.assembly_id = ar.referenced_assembly_id WHERE @iter_no = t.rank AND t.object_type = @assm AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- assembly referenced by udt INSERT #t1 (object_id ,object_name ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT asm.assembly_id ,asm.name ,t.object_db ,@assm ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.assembly_types AS at ON ( ( at.user_type_id = t.object_id ) AND ( at.is_user_defined = 1 ) ) JOIN sys.assemblies AS asm ON asm.assembly_id = at.assembly_id WHERE @iter_no = t.rank AND t.object_type = @udt AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- assembly referenced by udf, sp, uda, trigger INSERT #t1 (object_id ,object_name ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT asm.assembly_id ,asm.name ,t.object_db ,@assm ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.assembly_modules AS am ON ( ( am.object_id = t.object_id ) AND ( am.assembly_id >= 65536 ) ) JOIN sys.assemblies AS asm ON asm.assembly_id = am.assembly_id WHERE @iter_no = t.rank AND t.object_type IN ( @udf, @sp, @uda, @tr ) AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- Partition Schemes referenced by tables/views INSERT #t1 (object_id ,object_name ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT ps.data_space_id ,ps.name ,t.object_db ,@part_sch ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.indexes AS idx ON idx.object_id = t.object_id JOIN sys.partition_schemes AS ps ON ps.data_space_id = idx.data_space_id WHERE @iter_no = t.rank AND t.object_type IN ( @u, @v ) AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- Partition Function referenced by Partition Schemes INSERT #t1 (object_id ,object_name ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT pf.function_id ,pf.name ,t.object_db ,@part_func ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.partition_schemes AS ps ON ps.data_space_id = t.object_id JOIN sys.partition_functions AS pf ON pf.function_id = ps.function_id WHERE @iter_no = t.rank AND t.object_type = @part_sch AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- sp, udf, triggers referenced by plan guide INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT o.object_id ,o.name ,Schema_name(o.schema_id) ,t.object_db ,( CASE o.type WHEN 'P' THEN @sp WHEN 'TR' THEN @tr ELSE @udf END ) ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.plan_guides AS pg ON pg.plan_guide_id = t.object_id JOIN sys.objects AS o ON o.object_id = pg.scope_object_id WHERE @iter_no = t.rank AND t.object_type = @pg AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- objects referenced by synonym INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT o.object_id ,o.name ,Schema_name(o.schema_id) ,t.object_db ,( CASE WHEN o.type = 'U' THEN @u WHEN o.type = 'V' THEN @v WHEN o.type IN ( 'P', 'RF', 'PC' ) THEN @sp WHEN o.type = 'AF' THEN @uda ELSE @udf END ) ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,0 ,@iter_no + 1 FROM #t1 AS t JOIN sys.synonyms AS s ON s.object_id = t.object_id JOIN sys.objects AS o ON o.object_id = Object_id(s.base_object_name) AND o.type IN ( 'U', 'V', 'P', 'RF', 'PC', 'AF', 'TF', 'FN', 'IF', 'FS', 'FT' ) WHERE @iter_no = t.rank AND t.object_type = @synonym AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; -- uddt referenced by sequence. Used to find UDDT that is in sequence dependencies. INSERT #t1 (object_id ,object_name ,object_schema ,object_db ,object_type ,relative_id ,relative_name ,relative_schema ,relative_db ,relative_type ,schema_bound ,rank) SELECT tp.user_type_id ,tp.name ,Schema_name(tp.schema_id) ,t.object_db ,CASE tp.is_assembly_type WHEN 1 THEN @udt ELSE @uddt END ,t.object_id ,t.object_name ,t.object_schema ,t.object_db ,t.object_type ,1 ,@iter_no + 1 FROM #t1 AS t JOIN sys.sequences AS s ON s.object_id = t.object_id JOIN sys.types AS tp ON tp.user_type_id = s.user_type_id AND tp.schema_id != 4 WHERE @iter_no = t.rank AND t.object_type = @sequence AND ( t.object_svr IS NULL AND t.object_db = DB_NAME() ); SET @rows = @rows + @@rowcount; END SET @iter_no = @iter_no + 1; END UPDATE #t1 SET rank = 0; -- computing the degree of the nodes UPDATE #t1 SET degree = (SELECT Count(*) FROM #t1 t WHERE t.relative_id = #t1.object_id AND t.object_id != t.relative_id); -- perform the topological sorting SET @iter_no = 1; WHILE 1 = 1 BEGIN UPDATE #t1 SET rank = @iter_no WHERE degree = 0; -- end the loop if no more rows left to process IF ( @@rowcount = 0 ) BREAK; UPDATE #t1 SET degree = NULL WHERE rank = @iter_no UPDATE #t1 SET degree = (SELECT COUNT(*) FROM #t1 t WHERE t.relative_id = #t1.object_id AND t.object_id != t.relative_id AND t.object_id IN (SELECT tt.object_id FROM #t1 tt WHERE tt.rank = 0)) WHERE degree IS NOT NULL; SET @iter_no = @iter_no + 1; END --correcting naming mistakes of objects present in current database --This part need to be removed once SMO's URN comparision gets fixed DECLARE @collation SYSNAME; DECLARE db_cursor CURSOR FOR SELECT DISTINCT ISNULL(object_db, DB_NAME()) FROM #t1 AS t WHERE t.object_id IS NOT NULL AND t.object_svr IS NULL; OPEN db_cursor; FETCH next FROM db_cursor INTO @dbname; WHILE ( @@FETCH_STATUS <> -1 ) BEGIN IF ( DB_ID(@dbname) IS NULL ) BEGIN FETCH next FROM db_cursor INTO @dbname; CONTINUE; END SET @collation = (SELECT CONVERT(SYSNAME, Databasepropertyex(@dbname, 'Collation'))); SET @query = 'UPDATE #t1 set #t1.object_name = o.name,#t1.object_schema = sch.name from #t1 inner join ' + QUOTENAME(@dbname) + '.sys.objects as o on #t1.object_id = o.object_id INNER JOIN ' + QUOTENAME(@dbname) + '.sys.schemas as sch on sch.schema_id = o.schema_id where o.name = #t1.object_name collate ' + @collation + ' AND sch.name = #t1.object_schema collate ' + @collation; EXEC sp_executesql @query; FETCH next FROM db_cursor INTO @dbname; END CLOSE db_cursor; DEALLOCATE db_cursor; --final select SELECT ISNULL(t.object_id, 0) AS [object_id] ,t.object_name ,ISNULL(t.object_schema, '') AS [object_schema] ,ISNULL(t.object_db, '') AS [object_db] ,ISNULL(t.object_svr, '') AS [object_svr] ,t.object_type ,ISNULL(t.relative_id, 0) AS [relative_id] ,t.relative_name ,ISNULL(t.relative_schema, '') AS [relative_schema] ,relative_db ,ISNULL(t.relative_svr, '') AS [relative_svr] ,t.relative_type ,t.schema_bound ,ISNULL(CASE WHEN p.type = 'U' THEN @u WHEN p.type = 'V' THEN @v END, 0) AS [ptype] ,ISNULL(p.name, '') AS [pname] ,ISNULL(Schema_name(p.schema_id), '') AS [pschema] ,t.rank FROM #t1 AS t LEFT JOIN sys.objects AS o ON ( t.object_type = @tr AND o.object_id = t.object_id ) OR ( t.relative_type = @tr AND o.object_id = t.relative_id ) LEFT JOIN sys.objects AS p ON p.object_id = o.parent_object_id ORDER BY rank DESC; DROP TABLE #t1; DROP TABLE #t2; DROP TABLE #tempdep; IF @must_set_nocount_off > 0 SET nocount OFF;