获取跨dbs和pivot sql server 2012的所有表的行数

时间:2015-03-07 05:06:42

标签: sql sql-server sql-server-2012 pivot-table

我使用以下脚本来获取所有数据库的行数 这些数据库的结构完全相同。

USE [MyTestDb1];

SELECT 
    'MyTestDb1'as [Database Name], so.name AS [Table Name],   
    rows AS [RowCount]   
FROM 
    sysindexes AS si   
JOIN 
    sysobjects AS so on si.id = so.id   
WHERE 
    indid IN (0,1)   
    AND xtype = 'U'

USE [MyTestDb2];

SELECT 
   'MyTestDb2'as [Database Name], so.name AS [Table Name],   
    rows AS [RowCount]   
FROM 
    sysindexes AS si   
JOIN 
    sysobjects AS so on si.id = so.id   
WHERE 
    indid IN (0,1)  
    AND xtype = 'U'

在c#的运行时,根据我要比较的dbs数量来构建sql脚本,然后执行。

鉴于我想在同一台服务器上比较多个dbs的行 我似乎无法实现以下输出。我相信是我需要的支点 但似乎无法解决这个问题。

TableName   Db1     Db2   Db3    Db4
------------------------------------
Table1      10      10    10     10
Table2      13      13    13     13
Table3      10      10    10     10
Table4      10      10    10     10
Table5      10      10    10     10

有关如何以上述格式退货的任何建议/帮助吗?

非常感谢。

1 个答案:

答案 0 :(得分:0)

是。此时您需要PIVOT

首先声明一个变量来动态获取列名

DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + [Database Name] + ']', '[' + [Database Name] + ']')
               FROM    
               (
                    SELECT DISTINCT 'MyTestDb1'as [Database Name]   
                    FROM sysindexes AS si   
                        join sysobjects AS so on si.id = so.id   
                    WHERE indid IN (0,1)   
                    AND xtype = 'U'
                ) PV 
               ORDER BY [Database Name]

现在将结果作为数据库名称在行中的列和表名中进行。

DECLARE @query NVARCHAR(MAX)
SET @query = '-- This outer query forms your pivoted result
             SELECT * FROM 
             (
                SELECT ''MyTestDb1'' as [Database Name], so.name AS [Table Name],   
                rows AS [RowCount]   
                FROM sysindexes AS si   
                    join sysobjects AS so on si.id = so.id   
                WHERE indid IN (0,1)   
                AND xtype = ''U''
             ) x
             PIVOT 
             (
                 --Defines the values in each dynamic columns
                 MIN([RowCount])
                 -- Get the names from the @cols variable to show as column
                 FOR [Database Name] IN (' + @cols + ')
            ) p            
            ORDER BY [Table Name];' 

EXEC SP_EXECUTESQL @query

编辑:

我已将数据插入临时表以便于理解。 CTE1将csv转换为行,CTE2sys....获取数据。在最后一部分中,我们使用CROSS JOIN,因为根据您的要求,不需要INNER JOIN

DECLARE @PARAM VARCHAR(MAX)='DB1 | DB2 | DB3'

;WITH CTE1 AS
(
    SELECT LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'Database Name' 
    FROM  
    (         
         SELECT CAST ('<M>' + REPLACE(@PARAM, '|', '</M><M>') + '</M>' AS XML) AS Data              
    ) AS A 
    CROSS APPLY Data.nodes ('/M') AS Split(a)
)
,CTE2 AS
(
    SELECT so.name AS [Table Name],   
        rows AS [RowCount]   
    FROM sysindexes AS si   
        join sysobjects AS so on si.id = so.id   
    WHERE indid IN (0,1)   
    AND xtype = 'U'
)
SELECT [Database Name],[Table Name],[RowCount]
INTO #NEWTABLE
FROM CTE1 
CROSS JOIN CTE2

现在声明变量以获取pivot

的列
DECLARE @cols NVARCHAR (MAX)

SELECT @cols = STUFF((SELECT distinct ',' + QUOTENAME(DatabaseName) 
            FROM 
            (
                SELECT LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'DatabaseName' 
                FROM  
                (         
                     SELECT CAST ('<M>' + REPLACE(@PARAM, '|', '</M><M>') + '</M>' AS XML) AS Data              
                ) AS A 
                CROSS APPLY Data.nodes ('/M') AS Split(a)
            ) c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

现在转动查询

DECLARE @query NVARCHAR(MAX)
SET @query = '
SELECT * 
FROM
(
    SELECT [Database Name],[Table Name],[RowCount]
    FROM #NEWTABLE  
)TAB
PIVOT 
(
     MIN([RowCount])
     for [Database Name] in (' + @cols + ')
) as P' 

EXEC SP_EXECUTESQL @query