如何获取存储过程中引用的所有列的列表?

Tri*_*ped 2 sql t-sql sql-server stored-procedures sql-server-2012

我有许多使用 CTE、临时表、表变量和子查询的存储过程,我需要获取存储过程中使用的所有列(包括数据库、模式和表/视图)的列表。我不需要获取临时表、表变量或 CTE 中的列。我只需要在我的服务器上的数据库的表或视图中定义的引用列。

我尝试过sys.dm_sql_referenced_entitiessys.sql_expression_dependencies但它们在第一个选择查询后或在 CTE 中选择后不会返回列。

Ste*_*ner 5

执行存储过程时,它会被解析并编译为查询计划,该计划会被缓存,您可以通过 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')
Run Code Online (Sandbox Code Playgroud)

买者自负这取决于您如何定义“二手”。存储过程中的 CTE 可能引用表中的 5 列,但是当使用此 CTE 时,仅传递其中的 3 列。查询优化器可能会忽略这些额外字段并且不将它们包含在计划中。另一方面,优化器可能决定可以通过在输出中包含额外的字段来进行更有效的查询,以便稍后能够使用更好的索引。此代码将返回查询计划使用的列,它们可能不完全是存储过程代码中的列。