我有一个复杂的查询,其中包含多个表、视图和函数。函数和视图拆分为更多视图和函数,这些视图和函数可能在其中拆分为更多视图和函数。
此查询存在性能问题,因此我想获得一个清晰简洁的列表,其中列出了我的查询中引用的所有对象,这样我就有了调查的基础。如何获取此对象列表?
我有一个复杂的查询,其中包含多个表、视图和函数。函数和视图拆分为更多视图和函数,这些视图和函数可能在其中拆分为更多视图和函数。
此查询存在性能问题,因此我想获得一个清晰简洁的列表,其中列出了我的查询中引用的所有对象,这样我就有了调查的基础。如何获取此对象列表?
描述
写了这个存储过程,下面递归地列出了所有依赖的子对象和孩子的依赖对象和孩子的孩子......等。输入参数可以是 Stored Proc、User Function、View。可以轻松更改以获得第 5 列的唯一列表,无论对象被调用的级别以及深度和对象如何。
列
编码
--=========================================================================
--=========================================================================
--== utlGetAllDependentObjectsRecursive - Uses recursive common table
--== expression to recursively get all the dependent objects as well
--== as the child objects and child's child objects of a
--== Stored Procedure or View or Function. can be easily modified to
--== include all other types of Objects
--=========================================================================
--=========================================================================
CREATE PROCEDURE utlGetAllDependentObjectsRecursive
(
-- Supports Stored Proc, View, User Function, User Table
@PARAM_OBJECT_NAME VARCHAR(500)
)
AS
BEGIN
WITH CTE_DependentObjects AS
(
SELECT DISTINCT
b.object_id AS UsedByObjectId,
b.name AS UsedByObjectName, b.type AS UsedByObjectType,
c.object_id AS DependentObjectId,
c.name AS DependentObjectName , c.type AS DependenObjectType
FROM sys.sysdepends a
INNER JOIN sys.objects b ON a.id = b.object_id
INNER JOIN sys.objects c ON a.depid = c.object_id
WHERE b.type IN ('P','V', 'FN') AND c.type IN ('U', 'P', 'V', 'FN')
),
CTE_DependentObjects2 AS
(
SELECT
UsedByObjectId, UsedByObjectName, UsedByObjectType,
DependentObjectId, DependentObjectName, DependenObjectType,
1 AS Level
FROM CTE_DependentObjects a
WHERE a.UsedByObjectName = @PARAM_OBJECT_NAME
UNION ALL
SELECT
a.UsedByObjectId, a.UsedByObjectName, a.UsedByObjectType,
a.DependentObjectId, a.DependentObjectName, a.DependenObjectType,
(b.Level + 1) AS Level
FROM CTE_DependentObjects a
INNER JOIN CTE_DependentObjects2 b
ON a.UsedByObjectName = b.DependentObjectName
)
SELECT DISTINCT * FROM CTE_DependentObjects2
ORDER BY Level, DependentObjectName
END
我看到这篇文章来识别引用特定同义词的所有对象,并在递归 CTE 的答案中使用基本逻辑来识别与正在执行的顶级查询中的对象的逗号分隔列表相关的所有对象。
Declare @baseObjects Nvarchar(1000) = '[Schema].[Table],[Schema].[View],[Schema].[Function],[Schema].[StoredProc]',
@SQL Nvarchar(Max);
Declare @objects Table (SchemaName Varchar(512), TableName Varchar(512), ID Int, xtype Varchar(10));
Set @SQL = 'Select ss.name As SchemaName,
so.name As TableName,
so.id,
so.xtype
From sysobjects so
Join sys.schemas ss
On so.uid = ss.schema_id
Where so.id In (Object_ID(''' + Replace(@baseObjects,',','''),Object_ID(''') + '''))';
Insert @objects
Exec sp_executeSQL @SQL;
With test As
(
Select ss.name As SchemaName,
so.name As TableName,
so.id,
so.xtype
From sys.sql_expression_dependencies sed
Join @objects vo
On sed.referencing_id = vo.ID
Join sysobjects so
On sed.referenced_id = so.id
Join sys.schemas ss
On so.uid = ss.schema_id
Union All
Select ss.name As SchemaName,
so.name As TableName,
so.id,
so.xtype
From test
Join sys.sql_expression_dependencies sed
On sed.referencing_id = test.id
And sed.referencing_id <> sed.referenced_id
Join sysobjects so
On sed. referenced_id = so.id
Join sys.schemas ss
On so.uid = ss.schema_id
)
Select Distinct *
From test
Union
Select *
From @objects;
选中此项,您将获得所有递归对象。
WITH Refobjects
(referencing_object_name,referencing_object_type_desc)
AS
(
SELECT
o.name AS referencing_object_name,
o.type_desc AS referencing_object_type_desc
FROM
sys.sql_expression_dependencies sed
INNER JOIN
sys.objects o ON sed.referencing_id = o.[object_id]
WHERE
sed.referenced_entity_name = 'Your Object Name'
UNION ALL
SELECT
o.name AS referencing_object_name,
o.type_desc AS referencing_object_type_desc
FROM
sys.sql_expression_dependencies sed
INNER JOIN
sys.objects o ON sed.referencing_id = o.[object_id]
INNER JOIN Refobjects ON sed.referenced_entity_name = Refobjects.referencing_object_name
)
SELECT distinct * FROM Refobjects
Order by 2 desc,1 ;
在 SQL Server 2008 中,引入了两个新的动态管理函数来跟踪对象依赖关系:sys.dm_sql_referenced_entities和sys.dm_sql_referenced_entities:
1/ 返回引用给定实体的实体:
SELECT
referencing_schema_name, referencing_entity_name,
referencing_class_desc, is_caller_dependent
FROM sys.dm_sql_referencing_entities ('<TableName>', 'OBJECT')
2/ 返回对象引用的实体:
SELECT
referenced_schema_name, referenced_entity_name, referenced_minor_name,
referenced_class_desc, is_caller_dependent, is_ambiguous
FROM sys.dm_sql_referenced_entities ('<StoredProcedureName>', 'OBJECT');
另一种选择是使用 Red Gate 的一个非常有用的工具,称为SQL Dependency Tracker。
基于上面@Raju Chavan 的回答,效果很好。然而...
我添加了对schemas的支持,以及返回(和排序)递归级别,因此可以使用sp_refreshsqlmodule轻松将其转换为脚本以正确顺序刷新引用对象(请参见下面的第 3 点)。
WITH
cRefobjects AS (
SELECT o.name, s.name AS sch, o.type_desc, 1 AS level
FROM sys.sql_expression_dependencies sed
INNER JOIN sys.objects o ON o.object_id = sed.referencing_id
INNER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
WHERE (sed.referenced_schema_name = '<your schema>' OR sed.referenced_schema_name IS NULL)
AND sed.referenced_entity_name = '<your object name>'
UNION ALL
SELECT o.name, s.name AS sch, o.type_desc, cRefobjects.level + 1 AS level
FROM
sys.sql_expression_dependencies AS sed
INNER JOIN sys.objects o ON o.object_id = sed.referencing_id
INNER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
INNER JOIN cRefobjects ON sed.referenced_entity_name = cRefobjects.name
AND sed.referenced_schema_name = cRefobjects.sch
)
SELECT DISTINCT name, sch, type_desc, level
FROM cRefobjects
ORDER BY level, type_desc DESC, name;
有几点需要考虑:
OR sed.referenced_schema_name IS NULL
。如果您没有在数据库对象中遵循最佳实践,这可能会得到错误的引用对象。DECLARE @SQL NVARCHAR(4000); SET @SQL = '';
WITH
cRefobjects AS (
...
)
--SELECT DISTINCT name, sch, type_desc, level
SELECT @SQL = @SQL + 'EXEC sys.sp_refreshsqlmodule ''' + sch + '.' + name + '''' + CHAR(13)+CHAR(10)
FROM cRefobjects
ORDER BY level, type_desc DESC, name;
PRINT @SQL
我已经改进了上述答案,因为没有一个对我有用。我需要一种通过 sp_refreshsqlmodule 类型刷新复杂嵌套对象的方法。您需要将 <TYPE_NAME> 更新为您自己的。
以下方法对我有用:
WITH cRefobjects AS (
SELECT o.name, s.name AS sch, o.type, 1 AS level
FROM sys.sql_expression_dependencies sed
INNER JOIN sys.objects o ON o.object_id = sed.referencing_id
INNER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
WHERE (sed.referenced_schema_name = '<SCHEMA>' OR sed.referenced_schema_name IS NULL)
AND sed.referenced_entity_name = '<TYPE_NAME>'
UNION ALL
SELECT o.name, s.name AS sch, o.type, cRefobjects.level + 1 AS level
FROM
sys.sql_expression_dependencies AS sed
INNER JOIN sys.objects o ON o.object_id = sed.referencing_id
INNER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
INNER JOIN cRefobjects ON sed.referenced_entity_name = cRefobjects.name
AND sed.referenced_schema_name = cRefobjects.sch
)
SELECT name, MAX(level) as level, 'EXEC sys.sp_refreshsqlmodule @name = ''' + sch + '.' + name + '''', type
FROM cRefobjects
GROUP BY name, sch, type
ORDER BY level, type, name;