<<< And back to the article by clicking here ...
IF OBJECT_ID
(N'dbo.It_Depends')
IS NOT
NULL
DROP FUNCTION
dbo.It_Depends
GO
CREATE FUNCTION
dbo.It_Depends
(@ObjectName
Varchar(200),
@ObjectsOnWhichItDepends
bit)
RETURNS @References
TABLE (
ThePath VARCHAR(MAX),
--the ancestor objects delimited by a '/'
TheFullEntityName
VARCHAR(200),
TheType VARCHAR(20),
iteration INT
)
/**
summary:
>
This
Table function returns a a table giving the dependencies of the object whose
name
is
supplied as a parameter.
At
the moment, only objects are allowed as a parameter, You can specify whether you
want
those objects that rely on the object, or those on whom the object relies.
compatibility: SQL Server 2005 - SQL
Server 2012
Revisions:
-
Author: Phil Factor
Version: 1.1
Modification: Allowed both types of dependencies, returned full detail
table
date: 20 Sep 2015
ToDo: Must add assemblies, must allow
entities such as types to be specified
example:
- code: |
Use AdventureWorks
SELECT
space(iteration * 4) + TheFullEntityName + ' (' + rtrim(TheType) + ')'
FROM
dbo.It_Depends('Employee',0)
ORDER BY ThePath
- code: |
Select * from
dbo.It_Depends('Employee',1)
Select * from
dbo.It_Depends('Employee',0)
returns:
>
@references table, which has the name,
the type, the display order and th
e 'path' of each dependent object
**/
AS
BEGIN
DECLARE
@DatabaseDependencies
TABLE (
EntityName
VARCHAR(200),
EntityType CHAR(5),
DependencyType
CHAR(4),
TheReferredEntity
VARCHAR(200),
TheReferredType
CHAR(5)
)
INSERT
INTO
@DatabaseDependencies
( EntityName,
EntityType,
DependencyType,
TheReferredEntity,
TheReferredType )
-- tables that reference udts
SELECT
object_schema_name(o.object_id)
+ '.'
+ o.name,
o.type,
'hard',
ty.name,
'UDT'
FROM
sys.objects
o
INNER JOIN
sys.columns
AS c
ON c.object_ID
= o.object_id
INNER JOIN
sys.types
ty ON
ty.user_type_id
= c.user_type_id
WHERE
is_user_defined
= 1
UNION ALL
-- udtts that reference udts
SELECT
object_schema_name(tt.type_table_object_id)
+ '.'
+ tt.name,
'UDTT',
'hard',
ty.name,
'UDT'
FROM
sys.table_types
tt
INNER JOIN
sys.columns
AS c
ON c.object_id
= tt.type_table_object_id
INNER JOIN
sys.types
ty ON
ty.user_type_id
= c.user_type_id
WHERE
ty.is_user_defined
= 1
UNION ALL
--tables/views that reference triggers
SELECT
object_schema_name(o.object_id)
+ '.'
+ o.name,
o.type,
'hard',
object_schema_name(t.object_id)
+ '.'
+ t.name,
t.type
FROM
sys.objects
t
INNER JOIN
sys.objects
AS o
ON o.parent_object_id
= t.object_id
WHERE
o.type
= 'TR'
UNION ALL
-- tables that reference defaults via columns
(only default objects)
SELECT
object_schema_name(clmns.object_id)
+ '.'
+ object_name(clmns.object_id),
'U',
'hard',
object_schema_name(o.object_id)
+ '.'
+ o.name,
o.type
FROM
sys.objects
o
INNER JOIN
sys.columns
AS clmns
ON clmns.default_object_id
= o.object_id
WHERE
o.parent_object_id
= 0
UNION ALL
-- types that reference defaults (only default
objects)
SELECT
types.name,
'UDT',
'hard',
object_schema_name(o.object_id)
+ '.'
+ o.name,
o.type
FROM
sys.objects
o
INNER JOIN
sys.types
AS types
ON types.default_object_id
= o.object_id
WHERE
o.parent_object_id
= 0
UNION ALL
-- tables that reference rules via columns
SELECT
object_schema_name(clmns.object_id)
+ '.'
+ object_name(clmns.object_id),
'U',
'hard',
object_schema_name(o.object_id)
+ '.'
+ o.name,
o.type
FROM
sys.objects
o
INNER JOIN
sys.columns
AS clmns
ON clmns.rule_object_id
= o.object_id
UNION ALL
-- types that reference rules
SELECT
types.name,
'UDT',
'hard',
object_schema_name(o.object_id)
+ '.'
+ o.name,
o.type
FROM
sys.objects
o
INNER JOIN
sys.types
AS types
ON types.rule_object_id
= o.object_id
UNION ALL
-- tables that reference XmlSchemaCollections
SELECT
object_schema_name(clmns.object_id)
+ '.'
+ object_name(clmns.object_id),
'U',
'hard',
xml_schema_collections.name,
'XMLC'
FROM
sys.columns
clmns --should we
eliminate views?
INNER JOIN
sys.xml_schema_collections
ON
xml_schema_collections.xml_collection_id
= clmns.xml_collection_id
UNION ALL
-- table types that reference
XmlSchemaCollections
SELECT
object_schema_name(clmns.object_id)
+ '.'
+ object_name(clmns.object_id),
'UDTT',
'hard',
xml_schema_collections.name,
'XMLC'
FROM
sys.columns
AS clmns
INNER JOIN
sys.table_types
AS tt
ON tt.type_table_object_id
= clmns.object_id
INNER JOIN
sys.xml_schema_collections
ON
xml_schema_collections.xml_collection_id
= clmns.xml_collection_id
UNION ALL
-- procedures that reference
XmlSchemaCollections
SELECT
object_schema_name(params.object_id)
+ '.'
+ o.name,
o.type,
'hard',
xml_schema_collections.name,
'XMLC'
FROM
sys.parameters
AS params
INNER JOIN
sys.xml_schema_collections
ON
xml_schema_collections.xml_collection_id
= params.xml_collection_id
INNER JOIN
sys.objects
o ON
o.object_id
= params.object_id
UNION ALL
-- table references table
SELECT
object_schema_name(tbl.object_id)
+ '.'
+ tbl.name,
tbl.type,
'hard',
object_schema_name(referenced_object_id)
+ '.'
+ object_name(referenced_object_id),
'U'
FROM
sys.foreign_keys
AS fk
INNER JOIN
sys.tables
AS tbl
ON tbl.object_id
= fk.parent_object_id
UNION ALL
-- uda references types
SELECT
object_schema_name(params.object_id)
+ '.'
+ o.name,
o.type,
'hard',
types.name,
'UDT'
FROM
sys.parameters
AS params
INNER JOIN
sys.types
ON types.user_type_id
= params.user_type_id
INNER JOIN
sys.objects
o ON
o.object_id
= params.object_id
WHERE
is_user_defined
<> 0
UNION ALL
-- table,view references partition scheme
SELECT
object_schema_name(o.object_id)
+ '.'
+ o.name,
o.type,
'hard',
ps.name,
'PS'
FROM
sys.indexes
AS idx
INNER JOIN
sys.partitions
p ON
idx.object_id
= p.object_id
AND idx.index_id
= p.index_id
INNER JOIN
sys.partition_schemes
ps ON
idx.data_space_id
= ps.data_space_id
INNER JOIN
sys.objects
AS o
ON o.object_id
= idx.object_id
UNION ALL
-- partition scheme references partition
function
SELECT
ps.name,
'PS',
'hard',
object_schema_name(o.object_id)
+ '.'
+ o.name,
o.type
FROM
sys.partition_schemes
ps
INNER JOIN
sys.objects
AS o
ON ps.function_id
= o.object_id
UNION ALL
-- plan guide references sp, udf, triggers
SELECT
pg.name,
'PG',
'hard',
object_schema_name(o.object_id)
+ '.'
+ o.name,
o.type
FROM
sys.objects
o
INNER JOIN
sys.plan_guides
AS pg
ON pg.scope_object_id
= o.object_id
UNION ALL
-- synonym refrences object
SELECT
s.name,
'SYN',
'hard',
object_schema_name(o.object_id)
+ '.'
+ o.name,
o.type
FROM
sys.objects
o
INNER JOIN
sys.synonyms
AS s
ON object_id(s.base_object_name)
= o.object_id
UNION ALL
--
sequences that reference uddts
SELECT
s.name,
'SYN',
'hard',
object_schema_name(o.object_id)
+ '.'
+ o.name,
o.type
FROM
sys.objects
o
INNER JOIN
sys.sequences
AS s
ON s.user_type_id
= o.object_id
UNION ALL
SELECT DISTINCT
coalesce(object_schema_name(Referencing_ID)
+ '.',
'')
+ object_name(Referencing_ID),
referencer.type,
'soft',
coalesce(referenced_schema_name
+ '.',
'')
+ --likely schema name
coalesce(referenced_entity_name,
''),
--very likely entity name
referenced.type
FROM
sys.sql_expression_dependencies
INNER JOIN
sys.objects
referencer ON
referencing_id =
referencer.object_ID
INNER JOIN
sys.objects
referenced ON
referenced_id =
referenced.object_ID
WHERE
referencing_Class
= 1 AND
referenced_class =
1 AND referencer.type
IN
( 'v',
'tf',
'fn',
'p',
'tr',
'u' )
DECLARE @RowCount
INT
DECLARE @ii
INT
-- firstly we put in the object as a
seed.
INSERT
INTO @References
( ThePath,
TheFullEntityName,
theType,
iteration )
SELECT
coalesce(object_schema_name(object_ID)
+ '.',
'')
+ name,
coalesce(object_schema_name(object_ID)
+ '.',
'')
+ name,
type, 1
FROM
sys.objects
WHERE name
LIKE @ObjectName
-- then we just pull out the
dependencies at each level. watching out for
-- self-references and circular
references
SELECT
@rowcount =
@@ROWCOUNT,
@ii = 2
IF @ObjectsOnWhichItDepends<>0
--if we are looking for objects on which it depends
WHILE @ii
< 20 AND
@rowcount > 0
BEGIN
INSERT
INTO @References
( ThePath,
TheFullEntityName,
theType,
iteration )
SELECT DISTINCT
ThePath +
'/' +
TheReferredEntity,
TheReferredEntity,
TheReferredType,
@ii
FROM
@DatabaseDependencies
DatabaseDependencies
INNER JOIN
@References
previousReferences
ON
previousReferences.TheFullEntityName
= EntityName
AND
previousReferences.iteration
= @ii
- 1
WHERE
TheReferredEntity<>EntityName
AND
TheReferredEntity NOT
IN
(SELECT
TheFullEntityName FROM
@References)
SELECT
@rowcount =
@@rowcount
SELECT
@ii =
@ii + 1
END
ELSE --we are looking for objects
that depend on it.
WHILE @ii
< 20 AND
@rowcount > 0
BEGIN
INSERT
INTO @References
( ThePath,
TheFullEntityName,
theType,
iteration )
SELECT DISTINCT
ThePath +
'/' +
EntityName,
EntityName,
TheType,
@ii
FROM
@DatabaseDependencies
DatabaseDependencies
INNER JOIN
@References
previousReferences
ON
previousReferences.TheFullEntityName
= TheReferredEntity
AND
previousReferences.iteration
= @ii
- 1
WHERE
TheReferredEntity<>EntityName
AND EntityName
NOT IN
(SELECT
TheFullEntityName FROM
@References)
SELECT
@rowcount =
@@rowcount
SELECT
@ii =
@ii + 1
END
RETURN
END