![]() |
|
|
By: Dattatrey Sindol | 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 |
|
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.
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 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:
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:
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.
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:
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:
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.
| Share: | Share | Tweet |
|
![]() |
![]() |
Free SQL Server Learning |
| Friday, November 11, 2011 - 7:42:53 AM - GAJANAN | Read The Tip |
|
very informative and you would find 5th option pretty simple Thanks |
|
| 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 |
|
| 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, |
|
| 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:
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
|
|
|
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 |