T-SQL :: 列出所有表、列和透视内容

Posted

技术标签:

【中文标题】T-SQL :: 列出所有表、列和透视内容【英文标题】:T-SQL :: List all tables, columns and pivot content 【发布时间】:2021-12-28 13:40:33 【问题描述】:

我正在使用 SSMS 工具 Data Discovery and Classification。

该工具会自动搜索列名称,如%address%%name%%surname%%e-mail%%tax%%zip% 等... 并且很好地向您建议它可能是一个明智的数据。

事实上,在盎格鲁-撒克逊社会之外,列名不是英文的,但可以是法文、西班牙文、意大利文等。

所以我找到了一个查询,可以帮助我根据我的语言列出合理的数据:

SELECT schema_name(tab.schema_id) AS schema_name
    ,tab.name AS table_name
    ,col.name AS column_name
    ,t.name AS data_type
    ,NULL as Data_Preview
FROM sys.tables AS tab
INNER JOIN sys.columns AS col ON tab.object_id = col.object_id
LEFT JOIN sys.types AS t ON col.user_type_id = t.user_type_id
ORDER BY schema_name
    ,table_name
    ,column_id;

非常好。

但如果我可以添加一个名为 Content 的最后一列会更好

你能帮我存档吗?

这将是一个 DYO 数据发现和分类。

编辑:我可能表达得很糟糕。

我正在针对 AdventureWorks2019 运行 mz 查询:

schema_name table_name column_name data_type Data_Preview
Person Address AddressID int NULL
Person Address AddressLine1 nvarchar NULL
Person Address AddressLine2 nvarchar NULL
Person Address City nvarchar NULL
Person Address StateProvinceID int NULL
Person Address PostalCode nvarchar NULL

我想PIVOT 每一列的内容(比如说TOP 5)到最后一列

schema_name table_name column_name data_type Data_Preview
Person Address AddressID int 1,2,3,4,5
Person Address AddressLine1 nvarchar 1970 Napa Ct.,9833 Mt. Dias Blv.,7484 Roundtree Drive,9539 Glenside Dr,1226 Shoe St.
Person Address AddressLine2 nvarchar NULL,NULL,NULL,NULL,NULL
Person Address City nvarchar Bothell,Bothell,Bothell,Bothell,Bothell
Person Address StateProvinceID int 79,79,79,79,79
Person Address PostalCode nvarchar 98011,98011,98011,98011,98011

每个数据可以用逗号或其他分隔。结果是我想预览列中实际存在的数据:

这家伙显然是来存档的:

https://docs.microsoft.com/en-us/answers/questions/285445/how-to-get-column-values-in-one-comma-separated-va.html Pivot and comma Separated value https://www.mikekale.com/rows-to-comma-separated-lists-in-sql-server/

谢谢

【问题讨论】:

如果您可以提供一个包含几行示例数据的示例表以及基于您的示例数据的所需输出,那么这里真正有帮助的地方。 嗨@SeanLange,我更新了我的问题。谢谢 您将不得不为此使用动态 sql。我没有仔细查看 Nav 发布的解决方案,但这似乎是您所需要的。 仅供参考,该工具正在寻找敏感数据,而不是敏感数据。如果您的数据库中的数据是合理的,我怀疑该工具是否有任何想法。检测敏感数据(或者可能是非敏感数据)的工具可能会检查您的列是否具有正确的数据类型,例如将电话号码存储在varchar 中或将日期存储在int 中;两者都不明智。 另外,赏金描述是错误的,STUFF 除了将字符串的一部分替换为另一部分之外,没有做任何事情。 “魔术”由FOR XML PATH完成;所有STUFF 在此类解决方案中所做的就是删除第一个分隔符。 【参考方案1】:

已更新以支持 2016

DROP TABLE IF EXISTS #ColumnsToDisplay

SELECT    ROW_NUMBER () OVER (ORDER BY tab.name) AS Iteration,
          s.name AS SchemaName,
          tab.name AS table_name,
          col.column_id,
          col.name AS column_name,
          t.name AS data_type,
          col.max_length,
          col.precision AS PrecisionNumber,
          CAST(NULL AS VARCHAR(MAX)) AS DataSample
INTO      #ColumnsToDisplay
FROM      sys.tables AS tab
JOIN      sys.schemas AS s
    ON    s.schema_id = tab.schema_id
JOIN      sys.columns AS col
    ON    col.object_id = tab.object_id
LEFT JOIN sys.types AS t
    ON    col.user_type_id = t.user_type_id
     
DECLARE @Iterations       INT = 0,
        @CurrentIteration INT = 1;

SELECT @Iterations = MAX (Iteration)
FROM   #ColumnsToDisplay

WHILE @CurrentIteration <= @Iterations
BEGIN
    DECLARE @CurrentTableName  VARCHAR(100)   = '',
            @CurrentColumnName VARCHAR(100)   = '',
            @DynamicQuery      NVARCHAR(1000) = N''
    DECLARE @Sample VARCHAR(MAX)

    SET @CurrentTableName = '';
    SET @DynamicQuery = N'';
    SELECT @CurrentTableName = CONCAT (ttq.SchemaName, '.', ttq.table_name),
           @CurrentColumnName = ttq.column_name
    FROM   #ColumnsToDisplay AS ttq
    WHERE  ttq.Iteration = @CurrentIteration

    IF (@CurrentTableName = '')
    BEGIN
        SET @CurrentIteration += 1

        CONTINUE
    END

 -- SQL Server 2019
 -- SET @DynamicQuery = CONCAT (N'
 --       SELECT @Sample = STRING_AGG(t.ColumnData,'', '') 
 --       FROM (
 --               SELECT TOP 5  CAST(x.[', @CurrentColumnName, '] AS VARCHAR(MAX)) AS ColumnData 
 --               FROM ', @CurrentTableName, ' AS x 
 --               WHERE x.[', @CurrentColumnName, '] IS NOT NULL
 --       )t')

 -- SQL Server 2016 and lower where Stuff is supported   
    SET @DynamicQuery = CONCAT (N'
    SELECT @Sample =  STUFF((SELECT '', ''+ t.ColumnData  
    FROM (
            SELECT TOP 5 CAST(x.[', @CurrentColumnName, '] AS VARCHAR(MAX)) AS ColumnData 
            FROM ', @CurrentTableName, ' AS x 
            WHERE x.[', @CurrentColumnName, '] IS NOT NULL 
    ) AS t
       FOR XML PATH('''')),1,1,'''')')
        
    EXECUTE sys.sp_executesql @DynamicQuery,
                              N'@Sample VARCHAR(MAX) OUTPUT',
                              @Sample = @Sample OUTPUT

    UPDATE #ColumnsToDisplay
    SET    DataSample = @Sample
    WHERE  Iteration = @CurrentIteration

    SET @CurrentIteration += 1
END

SELECT ctd.Iteration,
       ctd.SchemaName,
       ctd.table_name,
       ctd.column_id,
       ctd.column_name,
       ctd.data_type,
       ctd.max_length,
       ctd.PrecisionNumber,
       ctd.DataSample
FROM   #ColumnsToDisplay AS ctd 

【讨论】:

谢谢@Nav,但我需要的更容易。我表达得很糟糕。我现在更新了我的问题。谢谢 您的代码已完成,但我可以在哪里选择结果? 我尝试修改您的代码以使其可用于 SQL Server 2016 以下示例:docs.microsoft.com/en-us/answers/questions/285445/…。 ` SET @DynamicQuery = CONCAT (N' SELECT @Sample = STUFF((SELECT t.ColumnData,'', '' FROM (SELECT TOP 5 CAST(x.', @CurrentColumnName, ' AS VARCHAR(MAX)) AS ColumnData FROM ', @CurrentTableName, 'AS x WHERE x.', @CurrentColumnName, ' IS NOT NULL FOR XML PATH('') ), 1, 1, ''))t')` 更新了查询以支持 sql server 2016 @Nav,使用QUOTENAME 而不是连接括号来包围列。这将处理标识符中的括号。

以上是关于T-SQL :: 列出所有表、列和透视内容的主要内容,如果未能解决你的问题,请参考以下文章

T-SQL:没有聚合的数据透视表

laravel 检索值匹配数据透视表的所有用户

数据透视表上的t-sql辅助数据透视表

如何使用 T-SQL 透视表?

T-SQL 中的数据透视表分区

T-SQL 列表、列