0

我希望能够返回给定 SQL 查询使用的所有字段的列表(最好是表详细信息)。例如查询的输入:

SELECT t1.field1, field3
FROM dbo.table1 AS t1
INNER JOIN dbo.table2 as t2
    ON t2.field2 = t1.field2
WHERE t2.field1 = 'someValue'

会回来

+--------+-----------+--------+
| schema | tablename | field  |
+--------+-----------+--------+
| dbo    | table1    | field1 |
| dbo    | table1    | field2 |
| dbo    | table1    | field3 |
| dbo    | table2    | field1 |
| dbo    | table2    | field2 |
+--------+-----------+--------+

它确实需要使用 SQL 内核(这个词对吗?引擎?)因为读者无法知道 field3 在 table1 而不是 table2 中。出于这个原因,我假设解决方案是 SQL。如果它也可以处理,则可以加分SELECT *

我尝试了一个使用 sqlparse ( https://sqlparse.readthedocs.io/en/latest/ ) 的 python 解决方案,但是在处理涉及临时表、子查询和 CTE 的更复杂的 SQL 查询时遇到了麻烦。别名的处理也非常困难(特别是如果查询在多个地方使用相同的别名)。显然它不能处理像field3上面没有表标识符的情况。也处理不了SELECT *

我希望 SQL Server Management Studio 中可能有更优雅的解决方案,甚至 SQL Server 本身中的某些功能。我们有来自 Redgate 的 SQL Prompt,它必须对它的智能感知、架构和它正在格式化的 SQL 查询有一定的了解。

更新:根据要求:我尝试这样做的原因是找出哪些Users可以在我们的组织内执行哪些 SSRS 报告。这完全取决于他们在给定报告中的所有数据集(在我们的例子中是 SQL 查询)使用的所有字段上GRANT SELECT分配给他们的权限。Roles我已经设法根据他们Users的. 我现在想扩展那些权限允许它们运行的​​报告。GRANT SELECTRoles

4

2 回答 2

1

我想我现在找到了答案。请注意:我目前没有执行这些功能的权限,所以我还没有测试它——当我有机会测试它时,我会更新答案。感谢@milivojeviCH 的回答。答案从这里复制:https ://stackoverflow.com/a/19852614/6709902

选择 SQL Server 执行计划中使用的所有列的最终目标解决了:

USE AdventureWorksDW2012

DBCC FREEPROCCACHE

SELECT dC.Gender, dc.HouseOwnerFlag, 
SUM(fIS.SalesAmount) AS SalesAmount 
FROM 
    dbo.DimCustomer dC INNER JOIN
    dbo.FactInternetSales fIS ON fIS.CustomerKey = dC.CustomerKey 
GROUP BY dC.Gender, dc.HouseOwnerFlag
ORDER BY dC.Gender, dc.HouseOwnerFlag
/*
query_hash          query_plan_hash
0x752B3F80E2DB426A  0xA15453A5C2D43765
*/

DECLARE @MyQ AS XML;

-- SELECT qstats.query_hash, query_plan_hash, qplan.query_plan AS [Query Plan],qtext.text 
SELECT @MyQ = qplan.query_plan 
 FROM sys.dm_exec_query_stats AS qstats 
  CROSS APPLY sys.dm_exec_query_plan(qstats.plan_handle) AS qplan 
  cross apply sys.dm_exec_sql_text(qstats.plan_handle) as qtext 
  where text like '% fIS %'
and query_plan_hash = 0xA15453A5C2D43765

SeLeCt @MyQ

;WITH xmlnamespaces (default 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT DISTINCT
    [Database] = x.value('(@Database)[1]', 'varchar(128)'),
    [Schema]   = x.value('(@Schema)[1]',   'varchar(128)'),
    [Table]    = x.value('(@Table)[1]',    'varchar(128)'),
    [Alias]    = x.value('(@Alias)[1]',    'varchar(128)'),
    [Column]   = x.value('(@Column)[1]',   'varchar(128)')
FROM   @MyQ.nodes('//ColumnReference') x1(x)

导致以下输出:

Database                  Schema Table            Alias Column
------------------------- ------ ---------------- ----- ----------------
NULL                      NULL   NULL             NULL  Expr1004
[AdventureWorksDW2012]    [dbo]  [DimCustomer]    [dC]  CustomerKey
[AdventureWorksDW2012]    [dbo]  [DimCustomer]    [dC]  Gender
[AdventureWorksDW2012]    [dbo]  [DimCustomer]    [dC]  HouseOwnerFlag
[AdventureWorksDW2012]    [dbo]  [FactInternetSal [fIS] CustomerKey
[AdventureWorksDW2012]    [dbo]  [FactInternetSal [fIS] SalesAmount
于 2020-02-28T15:29:40.867 回答
1

列表名可能很棘手,因为列名可能不明确甚至派生。但是,您几乎可以从任何查询或存储过程中获取列名、序列和类型。

例子

Select column_ordinal
      ,name
      ,system_type_name 
  From sys.dm_exec_describe_first_result_set('Select * from YourTable',null,null )  
于 2020-02-26T16:48:24.400 回答