我有许多使用 CTE、临时表、表变量和子查询的存储过程,我需要获取存储过程中使用的所有列(包括数据库、架构和表/ View )的列表。我不需要获取临时表、表变量或 CTE 中的列。我只需要在我的服务器上的数据库的表或 View 中定义的引用列。
我试过sys.dm_sql_referenced_entities
和 sys.sql_expression_dependencies
但它们不会在第一个选择查询之后返回列或在 CTE 中选择列。
最佳答案
执行存储过程时,它会被解析并编译为查询计划,该计划会被缓存,您可以通过 XML 格式的 sys.dm_exec_cached_plans 和 sys.dm_exec_query_plan 访问它。查询计划记录了解析代码的每个部分的“输出列表”。只需查询此 XML 即可查看存储过程使用了哪些列,如下所示:
--Execute the stored procedure to put its query plan in the cache
exec sys.sp_columns ''
DECLARE @TargetObject nvarchar(100) = 'sys.sp_columns';
WITH XMLNAMESPACES (
'http://schemas.microsoft.com/sqlserver/2004/07/showplan' as ns1
), CompiledPlan AS (
SELECT
(SELECT query_plan FROM sys.dm_exec_query_plan(cp.plan_handle)) qp,
(SELECT ObjectID FROM sys.dm_exec_sql_text(cp.plan_handle)) ob
FROM sys.dm_exec_cached_plans cp
WHERE objtype = 'Proc'
), ColumnReferences AS (
SELECT DISTINCT
ob,
p.query('.').value('./ns1:ColumnReference[1]/@Database', 'sysname') AS [Database],
p.query('.').value('./ns1:ColumnReference[1]/@Schema', 'sysname') AS [Schema],
p.query('.').value('./ns1:ColumnReference[1]/@Table', 'sysname') AS [Table],
p.query('.').value('./ns1:ColumnReference[1]/@Column', 'sysname') AS [Column]
FROM CompiledPlan
CROSS APPLY qp.nodes('//ns1:ColumnReference') t(p)
)
SELECT
[Database],
[Schema],
[Table],
[Column]
FROM ColumnReferences
WHERE
[Database] IS NOT NULL AND
ob = OBJECT_ID(@TargetObject, 'P')
买者自负这取决于您如何定义“二手”。存储过程中的 CTE 可能引用表中的 5 列,但是当使用此 CTE 时,仅传递其中的 3 列。查询优化器可能忽略这些额外字段并且不将它们包含在计划中。另一方面,优化器可能决定可以通过在输出中包含额外的字段来进行更有效的查询,以便稍后能够使用更好的索引。此代码将返回查询计划使用的列,它们可能不完全是存储过程代码中的列。
关于sql - 如何获取存储过程中引用的所有列的列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29023514/