【问题标题】:How to fetch the row count for all tables in a SQL SERVER database [duplicate]如何获取 SQL SERVER 数据库中所有表的行数 [重复]
【发布时间】:2010-02-08 12:37:21
【问题描述】:

我正在搜索可用于确定给定数据库的任何表中是否有任何数据(即行数)的 SQL 脚本。

这个想法是在存在任何行的情况下(在任何数据库中)重新实现数据库。

提到的数据库是Microsoft SQL SERVER

有人可以推荐一个示例脚本吗?

【问题讨论】:

    标签: sql sql-server rowcount


    【解决方案1】:

    以下 SQL 将为您获取数据库中所有表的行数:

    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
    

    输出将是一个表列表及其行数。

    如果您只想要整个数据库的总行数,请附加:

    SELECT SUM(row_count) AS total_row_count FROM #counts
    

    将为您提供整个数据库中总行数的单个值。

    【讨论】:

    • 已对此表示赞成 - 但认为重要的是要提及 sp_MSForEachTable 是一个未记录的过程 - afaik,这意味着 MS 不支持它并且可能会在不通知的情况下从未来版本中删除它?
    • @MarkD 是的,这是正确的,尽管它已经存在于几个版本的 SQL Server 中而没有改变。
    • 另外,这将对数据库中的所有表进行全表扫描,因此在生产服务器上运行它会导致“一点”磁盘 io。
    • 在 2016 年不起作用,“sp_MSForEachTable”不存在。
    • 试试这个你不需要创建临时表然后删除它。 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】:

    如果您想省去计算 (*) 300 万行表所需的时间和资源。根据 Kendal Van Dyke 的 SQL SERVER Central 试试这个。


    使用 sysindexes 的行计数 如果您使用的是 SQL 2000,则需要像这样使用 sysindexes:

    -- Shows all user tables and row counts for the current database 
    -- Remove OBJECTPROPERTY function call to include system objects 
    SELECT o.NAME,
      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 o.NAME
    

    如果您使用的是 SQL 2005 或 2008,查询 sysindexes 仍然可以工作,但 Microsoft 建议可能会在 SQL Server 的未来版本中删除 sysindexes,因此您应该改用 DMV,如下所示:

    -- Shows all user tables and row counts for the current database 
    -- Remove is_ms_shipped = 0 check to include system objects 
    -- i.index_id < 2 indicates clustered index (1) or hash table (0) 
    SELECT o.name,
      ddps.row_count 
    FROM sys.indexes AS i
      INNER JOIN sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID
      INNER JOIN sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID
      AND i.index_id = ddps.index_id 
    WHERE i.index_id < 2  AND o.is_ms_shipped = 0 ORDER BY o.NAME 
    

    【讨论】:

    • 好的,脚本可以工作,但在它的开头需要一个“使用数据库”。因此,虽然它按原样工作,但它具有误导性。
    • 在我的数据库中,接受的答案需要 10 秒。 这个答案取0! +1 为你 Keng。虽然我确实添加了 JOIN sys.schemas s ON s.schema_id = o.schema_id 并包含 s.Name 以查看合格的表名。
    • 请注意,使用 sysindexes 或 dm_dp_partition_stats 将为您提供行数的近似值
    • 确保您使用正确的数据库 - 如果您选择主 05/08 查询将返回空白。我建议将“USE [在此处输入您的数据库名称]”添加到答案中该查询的顶部。
    【解决方案3】:

    在 Azure 上工作,不需要存储过程。

    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 IN (0,1)
    

    Credit.

    【讨论】:

    • 什么是“AND t.name not like '%dss%'”?
    • @quillbreaker:不包括 SQL Azure Data Sync 创建的表
    • 这很好用。我坐下来说“这可能需要一段时间”,然后两秒钟就完成了。正在处理一个 528 表的数据库,但不知道它实际上有多大
    • 这在 SQL Server 2016 上运行良好;不需要这个“%dss%”
    • 漂亮,正如@trench 所说,我有点害怕,在生产环境中运行和查询一些命令,每个命令都有数亿条记录,在几个表中......但它只是一瞬间就过去了在 Azure 数据库上 。 Thnx 非常好用...
    【解决方案4】:

    我觉得这个比其他的好看。

    USE  [enter your db name here]
    GO
    
    SELECT      SCHEMA_NAME(A.schema_id) + '.' +
            --A.Name, SUM(B.rows) AS 'RowCount'  Use AVG instead of SUM
              A.Name, AVG(B.rows) AS 'RowCount'
    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
    GO
    

    【讨论】:

    • +1:此查询只需要data_reader 权限。
    • 我不知道为什么,但是这个查询没有准确计算所有表中的行数。某些表中的计数加倍。我发现 Rikin Patel 的查询是准确的。
    • @Dan 这个和 Rikin Patel 的区别在于,这个不检查 sys.partitions 条目的 index_id 是 0 还是 1。所以不仅仅是这样有些行翻了一番,就是有些行乘以它们拥有的索引数。因此,如果您有一个包含 100 行的表,并且您在其上定义了 3 个索引,则上述查询将显示该表的 3*100=300 行。
    • 上面的 cmets 是有效的 - 但我只需要了解哪些表有 一些 行,哪些没有。我只有data_reader 权限,所以其他解决方案都不适合我——只有这个。
    【解决方案5】:

    又短又甜

    sp_MSForEachTable 'DECLARE @t AS VARCHAR(MAX); 
    SELECT @t = CAST(COUNT(1) as VARCHAR(MAX)) 
    + CHAR(9) + CHAR(9) + ''?'' FROM ? ; PRINT @t'
    

    输出:

    【讨论】:

    • 多年后,这个非常适合快速查看每个表在 SQL Server 2017 上的行数。
    【解决方案6】:
    SELECT 
        sc.name +'.'+ ta.name TableName, SUM(pa.rows) RowCnt
    FROM 
        sys.tables ta
    INNER JOIN sys.partitions pa
        ON pa.OBJECT_ID = ta.OBJECT_ID
    INNER JOIN sys.schemas sc
        ON ta.schema_id = sc.schema_id
    WHERE ta.is_ms_shipped = 0 AND pa.index_id IN (1,0)
    GROUP BY sc.name,ta.name
    ORDER BY SUM(pa.rows) DESC
    

    【讨论】:

    • 只是想说明“pa.index_id IN (1,0)”条件的原因:它是将其限制为一张表的一组行数。更多信息在这里 - stackoverflow.com/a/456062/352349
    • 认为这不包括视图。除此之外它工作正常
    【解决方案7】:

    SQL Server 2005 或更高版本提供了一个相当不错的报告,显示表大小 - 包括行数等。它在标准报告中 - 并且是表的磁盘使用情况。

    以编程方式,有一个很好的解决方案: http://www.sqlservercentral.com/articles/T-SQL/67624/

    【讨论】:

    • 没有任何管理员权限,这很好用。 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
    【解决方案8】:

    不要使用SELECT COUNT(*) FROM TABLENAME,因为这是一个资源密集型操作。应该使用SQL Server Dynamic Management ViewsSystem Catalogs 来获取数据库中所有表的行数信息。

    【讨论】:

      【解决方案9】:

      我会对 Frederik 的解决方案做一些小改动。我会使用 sp_spaceused 系统存储过程,它还将包括数据和索引大小。

      declare c_tables cursor fast_forward for select table_name from information_schema.tables open c_tables declare @tablename varchar(255) declare @stmt nvarchar(2000) declare @rowcount int fetch next from c_tables into @tablename while @@fetch_status = 0 begin select @stmt = 'sp_spaceused ' + @tablename exec sp_executesql @stmt fetch next from c_tables into @tablename end close c_tables deallocate c_tables

      【讨论】:

        【解决方案10】:

        这是一种动态 SQL 方法,它也为您提供架构:

        DECLARE @sql nvarchar(MAX)
        
        SELECT
            @sql = COALESCE(@sql + ' UNION ALL ', '') +
                'SELECT
                    ''' + s.name + ''' AS ''Schema'',
                    ''' + t.name + ''' AS ''Table'',
                    COUNT(*) AS Count
                    FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name)
            FROM sys.schemas s
            INNER JOIN sys.tables t ON t.schema_id = s.schema_id
            ORDER BY
                s.name,
                t.name
        
        EXEC(@sql)
        

        如果需要,将其扩展为在实例中的所有数据库上运行(加入 sys.databases)将是微不足道的。

        【讨论】:

          【解决方案11】:

          从 information_schema.tables 视图中选择所有行,并为从该视图返回的每个条目发出 count(*) 语句。

          declare c_tables cursor fast_forward for
          select table_name from information_schema.tables
          
          open c_tables
          declare @tablename varchar(255)
          declare @stmt nvarchar(2000)
          declare @rowcount int
          fetch next from c_tables into @tablename
          
          while @@fetch_status = 0
          begin
          
              select @stmt = 'select @rowcount = count(*) from ' + @tablename
          
              exec sp_executesql @stmt, N'@rowcount int output', @rowcount=@rowcount OUTPUT
          
              print N'table: ' + @tablename + ' has ' + convert(nvarchar(1000),@rowcount) + ' rows'
          
              fetch next from c_tables into @tablename
          
          end
          
          close c_tables
          deallocate c_tables
          

          【讨论】:

            【解决方案12】:

            这是我最喜欢的 SQL 2008 解决方案,它将结果放入“TEST”临时表中,我可以使用它来排序并获得我需要的结果:

            SET NOCOUNT ON 
            DBCC UPDATEUSAGE(0) 
            DROP TABLE #t;
            CREATE TABLE #t 
            ( 
            [name] NVARCHAR(128),
            [rows] CHAR(11),
            reserved VARCHAR(18), 
            data VARCHAR(18), 
            index_size VARCHAR(18),
            unused VARCHAR(18)
            ) ;
            INSERT #t EXEC sp_msForEachTable 'EXEC sp_spaceused ''?''' 
            SELECT * INTO TEST FROM #t;
            DROP TABLE #t;
            SELECT  name, [rows], reserved, data, index_size, unused FROM TEST \
            WHERE ([rows] > 0) AND (name LIKE 'XXX%')
            

            【讨论】:

              【解决方案13】:
                  SELECT
                        SUM(sdmvPTNS.row_count) AS [DBRows]
                  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 = 0
                        AND sdmvPTNS.index_id < 2
                  GO
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2017-03-09
                • 1970-01-01
                • 2011-04-12
                • 1970-01-01
                • 1970-01-01
                • 2021-12-18
                • 1970-01-01
                • 2019-10-12
                相关资源
                最近更新 更多