【问题标题】:Query to list number of records in each table in a database查询以列出数据库中每个表中的记录数
【发布时间】:2009-09-18 10:27:50
【问题描述】:

如何列出数据库中每个表的行数。一些等价的

select count(*) from table1
select count(*) from table2
...
select count(*) from tableN

我会发布一个解决方案,但欢迎使用其他方法

【问题讨论】:

    标签: sql-server database


    【解决方案1】:

    如果您使用的是 SQL Server 2005 及更高版本,您也可以使用这个:

    SELECT 
        t.NAME AS TableName,
        i.name as indexName,
        p.[Rows],
        sum(a.total_pages) as TotalPages, 
        sum(a.used_pages) as UsedPages, 
        sum(a.data_pages) as DataPages,
        (sum(a.total_pages) * 8) / 1024 as TotalSpaceMB, 
        (sum(a.used_pages) * 8) / 1024 as UsedSpaceMB, 
        (sum(a.data_pages) * 8) / 1024 as DataSpaceMB
    FROM 
        sys.tables t
    INNER JOIN      
        sys.indexes i ON t.OBJECT_ID = i.object_id
    INNER JOIN 
        sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
    INNER JOIN 
        sys.allocation_units a ON p.partition_id = a.container_id
    WHERE 
        t.NAME NOT LIKE 'dt%' AND
        i.OBJECT_ID > 255 AND   
        i.index_id <= 1
    GROUP BY 
        t.NAME, i.object_id, i.index_id, i.name, p.[Rows]
    ORDER BY 
        object_name(i.object_id) 
    

    在我看来,它比sp_msforeachtable 输出更容易处理。

    【讨论】:

    • 知道为什么它会过滤掉名称以“dt”开头的表吗?我已经在网上看到了这个脚本,但没有关于这个标准的解释。我们都被控制了吗?
    • @Skaue:如果您将“数据库图”功能安装到您的数据库中,那么您将拥有一些表格,例如dtProperties 等;因为这些是“系统”表,所以我不想报告这些。
    • 是否可以在此脚本中为表名添加模式名称前缀?
    • 由于某种原因,此查询未返回所有表。我在数据库中有 382 个表。但是这个查询只返回 270 行(表信息)。删除 where 条件后,我得到 302 行。是不是因为其中一个 SYS 表中缺少某些表信息,所以连接忽略了它们。该数据库不包含任何系统表。
    • 这是有效的。你能修改它来比较两个数据库吗?
    【解决方案2】:

    我在http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=21021 找到的一个对我有帮助的 sn-p:

    select t.name TableName, i.rows Records
    from sysobjects t, sysindexes i
    where t.xtype = 'U' and i.id = t.id and i.indid in (0,1)
    order by TableName;
    

    【讨论】:

    • 我喜欢这个解决方案,虽然我会使用 JOIN 语法 from sysobjects t inner join sysindexes i on i.id = t.id and i.indid in (0,1) where t.xtype = 'U'
    • 我也更喜欢使用 JOIN 语句,但在我找到它时发布了代码 sn-p。 :)
    【解决方案3】:

    要在 SQL Management Studio 中获取该信息,请右键单击数据库,然后选择 Reports --> Standard Reports --> Disk Usage by Table。

    【讨论】:

    • 被低估的方法,这会快速生成一个可排序的报告,显示 # 行和数据的大小。
    【解决方案4】:
    SELECT 
        T.NAME AS 'TABLE NAME',
        P.[ROWS] AS 'NO OF ROWS'
    FROM SYS.TABLES T 
    INNER JOIN  SYS.PARTITIONS P ON T.OBJECT_ID=P.OBJECT_ID;
    

    【讨论】:

    • 此查询将为每个表上的每个索引返回一个行结果。添加 WHERE P.INDEX_ID IN (0,1) 以仅在适当的情况下将返回结果集限制为堆或聚集索引。
    【解决方案5】:

    As seen here, 这将返回正确的计数,其中使用元数据表的方法将仅返回估计值。

        CREATE PROCEDURE ListTableRowCounts 
        AS 
        BEGIN 
            SET NOCOUNT ON 
    
            CREATE TABLE #TableCounts
            ( 
                TableName VARCHAR(500), 
                CountOf INT 
            ) 
    
            INSERT #TableCounts
                EXEC sp_msForEachTable 
                    'SELECT PARSENAME(''?'', 1), 
                    COUNT(*) FROM ? WITH (NOLOCK)' 
    
            SELECT TableName , CountOf 
                FROM #TableCounts
                ORDER BY TableName 
    
            DROP TABLE #TableCounts
        END
        GO
    

    【讨论】:

    • 所以这听起来像是使用未记录的 stor proc sp_msForEachTable 与使用有时不是最新信息的系统表的妥协。 +1 并感谢您的链接
    【解决方案6】:
    sp_MSForEachTable 'DECLARE @t AS VARCHAR(MAX); 
    SELECT @t = CAST(COUNT(1) as VARCHAR(MAX)) 
    + CHAR(9) + CHAR(9) + ''?'' FROM ? ; PRINT @t'
    

    输出:

    【讨论】:

    • 我需要一些用于 Sql Server 2000 的东西。这行得通。谢谢!
    • 对于 SQL 2000,我将 MAX 替换为 8000
    【解决方案7】:

    幸运的是,SQL Server 管理工作室为您提供了有关如何执行此操作的提示。 这样做,

    1. 启动 SQL Server 跟踪并打开您正在执行的活动(筛选 如果您并不孤单,请通过您的登录 ID 设置应用程序名称 到 Microsoft SQL Server Management Studio),暂停跟踪并丢弃您迄今为止记录的所有结果;
    2. 然后,右键单击一个表并从弹出菜单中选择属性;
    3. 重新开始跟踪;
    4. 现在在 SQL Server Management Studio 中选择左侧的存储属性项;

    暂停跟踪,看看微软生成了什么 TSQL。

    在可能是最后一个查询中,您将看到以exec sp_executesql N'SELECT 开头的语句

    当您将执行的代码复制到 Visual Studio 时,您会注意到该代码生成了 microsoft 的工程师用来填充属性窗口的所有数据。

    当您对该查询进行适度修改时,您将得到如下内容:

    SELECT
    SCHEMA_NAME(tbl.schema_id)+'.'+tbl.name as [table], --> something I added
    p.partition_number AS [PartitionNumber],
    prv.value AS [RightBoundaryValue],
     fg.name AS [FileGroupName],
    CAST(pf.boundary_value_on_right AS int) AS [RangeType],
    CAST(p.rows AS float) AS [RowCount],
    p.data_compression AS [DataCompression]
    FROM sys.tables AS tbl
    INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and idx.index_id < 2
    INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int) AND p.index_id=idx.index_id
    LEFT OUTER JOIN sys.destination_data_spaces AS dds ON dds.partition_scheme_id = idx.data_space_id and dds.destination_id = p.partition_number
    LEFT OUTER JOIN sys.partition_schemes AS ps ON ps.data_space_id = idx.data_space_id
    LEFT OUTER JOIN sys.partition_range_values AS prv ON prv.boundary_id = p.partition_number and prv.function_id = ps.function_id
    LEFT OUTER JOIN sys.filegroups AS fg ON fg.data_space_id = dds.data_space_id or fg.data_space_id = idx.data_space_id
    LEFT OUTER JOIN sys.partition_functions AS pf ON  pf.function_id = prv.function_id
    

    现在查询并不完美,您可以对其进行更新以满足您可能遇到的其他问题,重点是,您可以利用微软的知识通过执行您感兴趣的数据来解决您遇到的大多数问题在并跟踪使用探查器生成的 TSQL。

    我喜欢认为 MS 工程师知道 SQL 服务器是如何工作的,并且它会生成 TSQL,该 TSQL 可以在您使用您正在使用的 SSMS 上的版本处理的所有项目上运行,因此它在各种版本的 previouse 上都非常好,现在和未来。

    请记住,不要只是复制,还要尝试理解它,否则您最终可能会得到错误的解决方案。

    沃尔特

    【讨论】:

      【解决方案8】:

      这种方法使用字符串连接来动态生成包含所有表及其计数的语句,就像原始问题中给出的示例一样:

                SELECT COUNT(*) AS Count,'[dbo].[tbl1]' AS TableName FROM [dbo].[tbl1]
      UNION ALL SELECT COUNT(*) AS Count,'[dbo].[tbl2]' AS TableName FROM [dbo].[tbl2]
      UNION ALL SELECT...
      

      最后用EXEC执行:

      DECLARE @cmd VARCHAR(MAX)=STUFF(
                          (
                              SELECT 'UNION ALL SELECT COUNT(*) AS Count,''' 
                                    + QUOTENAME(t.TABLE_SCHEMA) + '.' + QUOTENAME(t.TABLE_NAME) 
                                    + ''' AS TableName FROM ' + QUOTENAME(t.TABLE_SCHEMA) + '.' + QUOTENAME(t.TABLE_NAME)
                              FROM INFORMATION_SCHEMA.TABLES AS t
                              WHERE TABLE_TYPE='BASE TABLE'
                              FOR XML PATH('')
                          ),1,10,'');
      EXEC(@cmd);
      

      【讨论】:

      • 请注意,此解决方案包括架构的名称(可能很有用)
      • 这适用于 Azure 并且是唯一适用于外部表的一种
      【解决方案9】:

      首先想到的是使用 sp_msForEachTable

      exec sp_msforeachtable 'select count(*) from ?'
      

      虽然没有列出表名,所以可以扩展为

      exec sp_msforeachtable 'select parsename(''?'', 1),  count(*) from ?'
      

      这里的问题是,如果数据库有超过100个表,你会得到如下错误信息:

      查询已超过最大值 结果集的数量 显示在结果网格中。仅有的 前 100 个结果集是 显示在网格中。

      所以我最终使用表变量来存储结果

      declare @stats table (n sysname, c int)
      insert into @stats
          exec sp_msforeachtable 'select parsename(''?'', 1),  count(*) from ?'
      select 
          * 
      from @stats
      order by c desc
      

      【讨论】:

        【解决方案10】:

        在 SQL Refreence (http://www.codeproject.com/Tips/811017/Fastest-way-to-find-row-count-of-all-tables-in-SQL) 中查找所有表的行数的最快方法

        SELECT T.name AS [TABLE NAME], I.rows AS [ROWCOUNT] 
            FROM   sys.tables AS T 
               INNER JOIN sys.sysindexes AS I ON T.object_id = I.id 
               AND I.indid < 2 
        ORDER  BY I.rows DESC
        

        【讨论】:

          【解决方案11】:

          我想分享什么对我有用

          SELECT
                QUOTENAME(SCHEMA_NAME(sOBJ.schema_id)) + '.' + QUOTENAME(sOBJ.name) AS [TableName]
                , SUM(sdmvPTNS.row_count) AS [RowCount]
          FROM
                sys.objects AS sOBJ
                INNER JOIN sys.dm_db_partition_stats AS sdmvPTNS
                      ON sOBJ.object_id = sdmvPTNS.object_id
          WHERE 
                sOBJ.type = 'U'
                AND sOBJ.is_ms_shipped = 0x0
                AND sdmvPTNS.index_id < 2
          GROUP BY
                sOBJ.schema_id
                , sOBJ.name
          ORDER BY [TableName]
          GO
          

          数据库托管在 Azure 中,最终结果为:

          信用:https://www.mssqltips.com/sqlservertip/2537/sql-server-row-count-for-all-tables-in-a-database/

          【讨论】:

            【解决方案12】:

            接受的答案在 Azure SQL 上对我不起作用,这里是 one,它非常快并且完全符合我的要求:

            select t.name, s.row_count
            from sys.tables t
            join sys.dm_db_partition_stats s
              ON t.object_id = s.object_id
                and t.type_desc = 'USER_TABLE'
                and t.name not like '%dss%'
                and s.index_id = 1
            order by s.row_count desc
            

            【讨论】:

              【解决方案13】:

              你可以试试这个:

              SELECT  OBJECT_SCHEMA_NAME(ps.object_Id) AS [schemaname],
                      OBJECT_NAME(ps.object_id) AS [tablename],
                      row_count AS [rows]
              FROM sys.dm_db_partition_stats ps
              WHERE OBJECT_SCHEMA_NAME(ps.object_Id) <> 'sys' AND ps.index_id < 2
              ORDER BY 
                      OBJECT_SCHEMA_NAME(ps.object_Id),
                      OBJECT_NAME(ps.object_id)
              

              【讨论】:

                【解决方案14】:

                这个 sql 脚本给出了所选数据库中每个表的架构、表名和行数:

                SELECT SCHEMA_NAME(schema_id) AS [SchemaName],
                [Tables].name AS [TableName],
                SUM([Partitions].[rows]) AS [TotalRowCount]
                FROM sys.tables AS [Tables]
                JOIN sys.partitions AS [Partitions]
                ON [Tables].[object_id] = [Partitions].[object_id]
                AND [Partitions].index_id IN ( 0, 1 )
                -- WHERE [Tables].name = N'name of the table'
                GROUP BY SCHEMA_NAME(schema_id), [Tables].name
                order by [TotalRowCount] desc
                

                参考:https://blog.sqlauthority.com/2017/05/24/sql-server-find-row-count-every-table-database-efficiently/

                另一种方法:

                SELECT  o.NAME TABLENAME,
                  i.rowcnt 
                FROM sysindexes AS i
                  INNER JOIN sysobjects AS o ON i.id = o.id 
                WHERE i.indid < 2  AND OBJECTPROPERTY(o.id, 'IsMSShipped') = 0
                ORDER BY i.rowcnt desc
                

                【讨论】:

                  【解决方案15】:

                  这是我对这个问题的看法。它包含所有模式并仅列出带有行的表。 YMMV

                  select distinct schema_name(t.schema_id) as schema_name, t.name as 
                  table_name, p.[Rows]
                  from sys.tables as t
                  INNER JOIN sys.indexes as i ON t.OBJECT_ID = i.object_id
                  INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = 
                  p.index_id
                  where p.[Rows] > 0
                  order by schema_name;
                  

                  【讨论】:

                    【解决方案16】:

                    如果你使用 MySQL >4.x,你可以使用这个:

                    select TABLE_NAME, TABLE_ROWS from information_schema.TABLES where TABLE_SCHEMA="test";
                    

                    请记住,对于某些存储引擎,TABLE_ROWS 是一个近似值。

                    【讨论】:

                    • 他在他的帖子(作为标签)中提到了“sql-server”,即 Microsoft SQL Server
                    【解决方案17】:

                    我认为最短、最快和最简单的方法是:

                    SELECT
                        object_name(object_id) AS [Table],
                        SUM(row_count) AS [Count]
                    FROM
                        sys.dm_db_partition_stats
                    WHERE
                        --object_schema_name(object_id) = 'dbo' AND 
                        index_id < 2
                    GROUP BY
                        object_id
                    

                    【讨论】:

                      【解决方案18】:
                      USE DatabaseName
                      CREATE TABLE #counts
                      (
                          table_name varchar(255),
                          row_count int
                      )
                      
                      EXEC sp_MSForEachTable @command1='INSERT #counts (table_name, row_count) SELECT ''?'', COUNT(*) FROM ?'
                      SELECT table_name, row_count FROM #counts ORDER BY table_name, row_count DESC
                      DROP TABLE #counts
                      

                      【讨论】:

                        【解决方案19】:

                        从这个问题: https://dba.stackexchange.com/questions/114958/list-all-tables-from-all-user-databases/230411#230411

                        我在@Aaron Bertrand 提供的列出所有数据库和所有表的答案中添加了记录数。

                        DECLARE @src NVARCHAR(MAX), @sql NVARCHAR(MAX);
                        
                        SELECT @sql = N'', @src = N' UNION ALL 
                        SELECT ''$d'' as ''database'', 
                            s.name COLLATE SQL_Latin1_General_CP1_CI_AI as ''schema'',
                            t.name COLLATE SQL_Latin1_General_CP1_CI_AI as ''table'' ,
                            ind.rows as record_count
                          FROM [$d].sys.schemas AS s
                          INNER JOIN [$d].sys.tables AS t ON s.[schema_id] = t.[schema_id]
                          INNER JOIN [$d].sys.sysindexes AS ind ON t.[object_id] = ind.[id]
                          where ind.indid < 2';
                        
                        SELECT @sql = @sql + REPLACE(@src, '$d', name)
                          FROM sys.databases
                          WHERE database_id > 4
                            AND [state] = 0
                            AND HAS_DBACCESS(name) = 1;
                        
                        SET @sql = STUFF(@sql, 1, 10, CHAR(13) + CHAR(10));
                        
                        PRINT @sql;
                        --EXEC sys.sp_executesql @sql;
                        

                        【讨论】:

                          【解决方案20】:

                          您可以复制、粘贴并执行这段代码,以将所有表记录计数放入一个表中。注意:代码注释有说明

                          create procedure RowCountsPro
                          as
                          begin
                          --drop the table if exist on each exicution
                          IF OBJECT_ID (N'dbo.RowCounts', N'U') IS NOT NULL 
                          DROP TABLE dbo.RowCounts;
                          -- creating new table
                          CREATE TABLE RowCounts 
                          ( [TableName]            VARCHAR(150)
                          , [RowCount]               INT
                          , [Reserved]                 NVARCHAR(50)
                          , [Data]                        NVARCHAR(50)
                          , [Index_Size]               NVARCHAR(50)
                          , [UnUsed]                   NVARCHAR(50))
                          --inserting all records
                          INSERT INTO RowCounts([TableName], [RowCount],[Reserved],[Data],[Index_Size],[UnUsed])
                          --  "sp_MSforeachtable" System Procedure, 'sp_spaceused "?"' param to get records and resources used
                          EXEC sp_MSforeachtable 'sp_spaceused "?"' 
                          -- selecting data and returning a table of data
                          SELECT [TableName], [RowCount],[Reserved],[Data],[Index_Size],[UnUsed]
                          FROM RowCounts
                          ORDER BY [TableName]
                          end
                          

                          我已经测试了这段代码,它在 SQL Server 2014 上运行良好。

                          【讨论】:

                            【解决方案21】:
                                    SELECT ( Schema_name(A.schema_id) + '.' + A.NAME ) AS TableName,
                             Sum(B.rows)AS RecordCount 
                                FROM   sys.objects A INNER JOIN sys.partitions B 
                                ON A.object_id = B.object_id WHERE  A.type = 'U' 
                                    GROUP  BY A.schema_id,A.NAME ;
                            

                            QUERY_PHOTO

                            QUERY_RESULT_PHOTO

                            【讨论】:

                              【解决方案22】:

                              Shnugo 的答案是唯一在 Azure 中使用 Externa Tables 的答案。 (1) Azure SQL 根本不支持 sp_MSforeachtable 并且 (2) 外部表的 sys.partitions 中的行始终为 0。

                              【讨论】:

                                【解决方案23】:
                                select T.object_id, T.name, I.indid, I.rows 
                                  from Sys.tables T 
                                  left join Sys.sysindexes I 
                                    on (I.id = T.object_id and (indid =1 or indid =0 ))
                                 where T.type='U'
                                

                                这里indid=1 表示一个集群索引,indid=0 是一个堆

                                【讨论】:

                                • 您好,欢迎来到 Stack Overflow。这个答案与a year old 的答案相同......无需再次发布。
                                猜你喜欢
                                • 2010-12-10
                                • 2011-05-19
                                • 1970-01-01
                                • 2014-08-01
                                • 1970-01-01
                                • 2014-10-19
                                • 2023-02-07
                                • 2018-05-02
                                相关资源
                                最近更新 更多