solving sql server problems for millions of dbas and developers since 2006



SQL Server DBA Tips SQL Server Developer Tips SQL Server Business Intelligence Tips SQL Server Career Tips SQL Server Tip Categories SQL Server Tutorials SQL Server Webcasts SQL Server Whitepapers SQL Server Tools SQL Server Questions and Answers MSSQLTips Authors About MSSQLTips SQL Server User Groups MSSLQTips Giveaways MSSQLTips Advertising Options

MSSQLTips Facebook Page MSSQLTips LinkedIn Page MSSQLTips RSS Feed MSSQLTips Twitter Page MSSQLTips Google+ Page





SQL Server Row Count for all Tables in a Database

By: | Read Comments (12) | Print

Datta has over 5 years of experience in the IT industry working with SQL Server, SSIS, SSAS, SSRS.

Related Tips: More

Problem

I am a database tester and one of my tasks involves getting the row counts from all the tables in the source database and comparing it against the corresponding table row counts in the target database. How do I get the row counts from all the tables in a SQL Server Database? What are the different approaches to get this information?  Check out this tip to get these questions and more answered.

Solution

It is a common step in any ETL project to validate the row counts between source and target databases as part of the testing phase. Getting the row count from each table one by one and comparing and consolidating the results can be a tedious task. Hence any script/solution which can get the row count information from all the tables in a database can be really helpful and effective thereby considerably reducing the effort involved. In this tip we will see four different approaches to get the row counts from all the tables in a SQL Server database.

Let's take a look at each of the approaches:

  • sys.partitions Catalog View
  • sys.dm_db_partition_stats Dynamic Management View (DMV)
  • sp_MSforeachtable System Stored Procedure
  • COALESCE() Function

Approach 1: sys.partitions Catalog View

sys.partitions is an Object Catalog View and contains one row for each partition of each of the tables and most types of indexes (Except Fulltext, Spatial, and XML indexes). Every table in SQL Server contains at least one partition (default partition) even if the table is not explicitly partitioned.

The T-SQL query below uses the sys.partitions Catalog View to capture the row counts for all tables in a database.

SELECT
      QUOTENAME(SCHEMA_NAME(sOBJ.schema_id)) + '.' + QUOTENAME(sOBJ.name) AS [TableName]
      , SUM(sPTN.Rows) AS [RowCount]
FROM 
      sys.objects AS sOBJ
      INNER JOIN sys.partitions AS sPTN
            ON sOBJ.object_id = sPTN.object_id
WHERE
      sOBJ.type = 'U'
      AND sOBJ.is_ms_shipped = 0x0
      AND index_id < 2 -- 0:Heap, 1:Clustered
GROUP BY 
      sOBJ.schema_id
      , sOBJ.name
ORDER BY [TableName]
GO

Below are the highlights of this approach:

  1.  Requires membership in the public role.
  2. Can be used even when working with source systems which offer limited privileges such as read-only.

Approach 2: sys.dm_db_partition_stats Dynamic Management View (DMV)

sys.dm_db_partition_stats is a Dynamic Management View (DMV) which contains one row per partition and displays the information about the space used to store and manage different data allocation unit types - IN_ROW_DATA, LOB_DATA and ROW_OVERFLOW_DATA.

The T-SQL query below uses the sys.dm_db_partition_stats DMV to capture the row counts for all tables in a database.

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

Below are the highlights of this approach:

  1. VIEW DATABASE STATE permissions are required in the database.
  2. The values in the sys.dm_db_partition_stats DMV are reset on server restart or when an object/partition is dropped and recreated.

In general, querying the Dynamic Management Views (DMVs), requires VIEW SERVER STATE or VIEW DATABASE STATE permissions based on the Dynamic Management View/Function which is being queried.


Approach 3: sp_MSforeachtable System Stored Procedure

sp_MSforeachtable is an undocumented system stored procedure which can be used to iterate through each of the tables in a database. In this approach we will get the row counts from each of the tables in a given database in an iterative fashion and display the record counts for all the tables at once.

The T-SQL query below uses the sp_MSforeachtable system stored procedure to iterate through each of the tables to capture the row count for all the tables in a database.

DECLARE @TableRowCounts TABLE ([TableName] VARCHAR(128), [RowCount] INT) ;
INSERT INTO @TableRowCounts ([TableName], [RowCount])
EXEC sp_MSforeachtable 'SELECT ''?'' [TableName], COUNT(*) [RowCount] FROM ?' ;
SELECT [TableName], [RowCount]
FROM @TableRowCounts
ORDER BY [TableName]
GO

Below are the highlights of this approach:

  1. This is an iterative approach which captures the row count for each of the individual tables, puts them together and displays the results for all the tables.
  2. sp_MSforeachtable is an undocumented system stored procedure.
  3. This approach can be used for testing purposes but it is not recommended for use in any production code. sp_MSforeachtable is an undocumented system stored procedure and may change anytime without prior notification from Microsoft.

Approach 4: COALESCE() Function

The COALESCE() function is used to return the first non-NULL value/expression among its arguments. In this approach we will build a query to get the row count from each of the individual tables with UNION ALL to combine the results and run the entire query.

The T-SQL query below uses the COALESCE() function to iterate through each of the tables to dynamically build a query to capture the row count from each of the tables (individual COUNT queries combined using UNION ALL) and provides the row counts for all the tables in a database.

DECLARE @QueryString NVARCHAR(MAX) ;
SELECT @QueryString = COALESCE(@QueryString + ' UNION ALL ','')
                      + 'SELECT '
                      + '''' + QUOTENAME(SCHEMA_NAME(sOBJ.schema_id))
                      + '.' + QUOTENAME(sOBJ.name) + '''' + ' AS [TableName]
                      , COUNT(*) AS [RowCount] FROM '
                      + QUOTENAME(SCHEMA_NAME(sOBJ.schema_id))
                      + '.' + QUOTENAME(sOBJ.name) + ' WITH (NOLOCK) '
FROM sys.objects AS sOBJ
WHERE
      sOBJ.type = 'U'
      AND sOBJ.is_ms_shipped = 0x0
ORDER BY SCHEMA_NAME(sOBJ.schema_id), sOBJ.name ;
EXEC sp_executesql @QueryString
GO

Below are the highlights of this approach:

  1. Can be used in cases where the number of tables is huge like say few hundred tables. This query can be modified to capture the row counts from a set of tables at one time instead of all the tables which might otherwise put a lot of load on the system.
  2. Can be used even when working with source systems which offer limited privileges such as read-only.

Below is sample output from AdventureWorksDW database. Note - the results in your AdventureWorksDW database might vary slightly from what is displayed below due to various reasons like the version of database being used, any changes/data manipulation done on the database for testing purposes, etc.

AdventureWorks Row Count

Next Steps



Related Tips: More | Become a paid author


Last Update: 11/11/2011

Share: Share 






Comments and Feedback:

Friday, November 11, 2011 - 7:42:53 AM - GAJANAN Read The Tip

very informative

and you would find 5th option pretty simple

- View Object Explorer details
- Click Tables
- and RMC on Headers of the table and Click ROw Count it will give you row count for all the tbale objects.

Thanks
GP


Friday, November 11, 2011 - 11:58:39 AM - Jason Read The Tip

GP, that is manually. We often need this automatic way (insert into a data history, for example). DBA has to do work most efficient way.

Jason

http://usa.redirectme.net


Friday, November 11, 2011 - 1:27:30 PM - Dattatrey Sindol Read The Tip

Thanks for the feedback GP and posting one more way to get the row count (manual approach).

However, as Jason called out, quite often, we need automatic ways to get row counts for for performing tasks like Auditing, Row Count Validation, etc.

Thank you both for your feedback and additional information.


Friday, November 11, 2011 - 5:09:28 PM - Prabhakar Read The Tip

Hello Friends,

I Reckon, the below query would do the trick.

SELECT DISTINCT OBJECT_NAME(ID),ID,ROWCNT FROM SYSINDEXES WHERE INDID < 2

Regards,

Prabhakar J


Friday, November 11, 2011 - 5:43:34 PM - Adam M Read The Tip

Hello,

I use foreachtable but do it a bit differently. I found count(*) could really take a long time so I used:

 

IF OBJECT_ID('tempdb..#sizeo') IS NOT NULL 

DROP TABLE #sizeo

 

CREATE TABLE #sizeo (

NAME VARCHAR(100),

ROWS INT,

reserved VARCHAR(50),

DATA VARCHAR(50),

index_size VARCHAR(50), 

unused VARCHAR(50)

)

 

EXEC sp_msforeachtable '

insert into #sizeo

EXEC sp_spaceused ''?''

'

SELECT name, ROWS FROM #sizeo

 

I enjoyed the other ways to find it though. Thanks!


Saturday, November 12, 2011 - 1:08:24 AM - Dattatrey Sindol Read The Tip

Hello Prabhakar,

Please note that "sys.sysindexes" is a compatibility view provided for backward compatibility. We should avoid using this as this feature will be removed in future versions of SQL Server.

You can refer to the following URLs for more details:

Best Regards,

Datta


Saturday, November 12, 2011 - 1:18:19 AM - Dattatrey Sindol Read The Tip

Hello Adam,

Your approach works well too! The differences I see are storing the results in Temp Table instead of Table Variable, and use of sp_spaceused system stored procedure. However, with the use of sp_spaceused, it does not provide the schema related information.

Thanks for sharing.

 

Best Regards,

Datta


Saturday, November 12, 2011 - 8:34:21 AM - Jeremy Kadlec Read The Tip

Everyone,

Thank you for all of the comments on this tip.  It is good to see how other SQL Server Professionals in the community address this need.

Thank you,
Jeremy Kadlec


Monday, November 14, 2011 - 8:56:46 AM - Prabhakar Read The Tip

Hello Datta,

Thanks for the info.

Happy coding,

Prabhakar J


Monday, March 19, 2012 - 4:00:16 PM - vipul Read The Tip

what if I want to capture row counts off of SQL Views?  Don't want to use any deprecated or unsupported functionality.  No MSForeach, or sysindexes.  suggestions?


Thursday, March 22, 2012 - 1:17:01 AM - Dattatrey Sindol Read The Tip

Hi Vipul,

When it comes to views, it gets a little tricky depending on the type of view(s) you are dealing. Based on your preferences mentioned above, I would suggest you use Approach# 4 mentioned above (ofcourse you need to change type = 'U' to type = 'V') with the following considerations in mind:

  • Identify the complexity of the views based on number of tables involved, JOIN conditions, etc. Basically evaluate the complexity based on the T-SQL present inside your view. Group the views into Simple, Medium, & Complex.
  • You could group few views and fire the query in Approach# 4.
  • As the view complexity increases then the number of veiws grouped in each query should be reduced accordingly.
  • In some scenarios based on my experience, source systems expose the data to downstream applications in the form of views which map 1:1 to the underlying tables without any filters/transformations. In this type of scenario, I don't see any much performance impact and Approach# 4 can be used here as well.

Hope that helps.


Thursday, March 22, 2012 - 1:56:34 PM - Jason Read The Tip

I modified sp_spaceused to return correct schema name. In the parsename function, you can recode calling parsename. Imagine you have two objects of the same name in two different schema. That provides row count, space used including index etc.

Regards,

Jason

http://dbace.us

 



Post a Comment or Question

Keep it clean and stay on the subject or we may delete your comment.
Your email address is not published. Required fields are marked with an asterisk (*)

*Name   *Email   Notify for updates
Comments
*Enter Code refresh code


 
New SQL Monitor v3.0

New SQL Monitor v3.0


Sponsor Information
Try the award winning SQL diagnostic manager as a free 14-day trial!

Quickly and accurately deploy database changes with Red Gate's SQL Compare - the industry standard comparison and deployment tool.

SQL Servers keeping you up at night? Contact expert SQL Server consultants for a Health Check.

Free Trial: Get Proactive Insight with SpotlightŪ for SQL Server Enterprise.

Join the over million SQL Server Professionals who get their issues resolved daily.

Free Learning - Introduction to SQL Azure Delivered by Herve Roggero on Wednesday, June 13 @ 3:00 PM EST


Copyright (c) 2006-2012 Edgewood Solutions, LLC All rights reserved
privacy | disclaimer | copyright | advertise | about
authors | contribute | feedback | giveaways | user groups
Some names and products listed are the registered trademarks of their respective owners.


Edgewood Solutions LLC | MSSharePointTips.com | MSSQLTips.com