MS SQL 2005 (T-SQL) Row Count for Each Table

At work I needed a solution to give me a count of how many rows each table contained. I've always liked phpMyAdmin's ability to list all the tables and show their size and row count. I've found it immensely helpful. However, I couldn't find anything similar for SQL Server Manager Studio 2005. I found a blog post that pointed me in the right direction on how to get the row counts, but I couldn't get their script to run on the SQL Server 2005. Since I figured this would be a useful script to have I would re-write it and comment it for others. Here it is:

SQL:
  1. -- Select Database
  2. -- This should be the only configuration you need
  3. USE Your_Database
  4. GO
  5.  
  6. -- Create a cursor to loop through the System Ojects and get each table name
  7. DECLARE TBL_CURSOR CURSOR
  8. -- Declare the SQL Statement to cursor through
  9. FOR ( SELECT Name FROM Sysobjects WHERE Type='U' )
  10.  
  11. -- Declare the @SQL Variable which will hold our dynamic sql
  12. DECLARE @SQL NVARCHAR(MAX);
  13. SET @SQL = '';
  14. -- Declare the @TblName Variable which will hold the name of the current table
  15. DECLARE @TblName NVARCHAR(MAX);
  16.  
  17. -- Open the Cursor
  18. OPEN TBL_CURSOR
  19.  
  20. -- Setup the Fetch While that will loop through our cursor and set @TblName
  21. FETCH NEXT FROM TBL_CURSOR INTO @TblName
  22. -- Do this while we are not at the end of the record set
  23. WHILE (@@FETCH_STATUS <> -1)
  24. BEGIN
  25. -- Appeand this table's select count statement to our sql variable
  26. SET @SQL = @SQL + ' ( SELECT '''+@TblName+''' AS Table_Name,COUNT(*) AS Count FROM '+@TblName+' ) UNION';
  27.  
  28. -- Pull the next record
  29. FETCH NEXT FROM TBL_CURSOR INTO @TblName
  30. -- End the Cursor Loop
  31. END
  32.  
  33. -- Close and Clean Up the Cursor
  34. CLOSE TBL_CURSOR
  35. DEALLOCATE TBL_CURSOR
  36.  
  37. -- Since we were adding the UNION at the end of each part, the last query will have
  38. -- an extra UNION. Lets  trim it off.
  39. SET @SQL = LEFT(@SQL,LEN(@SQL)-6);
  40.  
  41. -- Lets do an Order By. You can pick between Count and Table Name by picking which
  42. -- line to execute below.
  43. SET @SQL = @SQL + ' ORDER BY Count';
  44. --SET @SQL = @SQL + ' ORDER BY Table_Name';
  45.  
  46. -- Now that our Dynamic SQL statement is ready, lets execute it.
  47. EXEC (@SQL);
  48. GO

How it works

A basic description would be it gets a listing of each table inside the the System Objects table and creates a Dynamic SQL Statement that get a count from each table and return a record set with the Table's name and count. Pretty straight forward, and I commented just about every little thing in the script so it should be easy to follow along. Let me know if you have any suggestions or tips for making it better. Thanks!

No related posts.

Posted in Programming. Tagged with , , , , .

7 Responses

Comments RSS Feed.

  1. Hans Callesen said

    replaced cursor with a table vriable & a while loop. More efficient , though not noticable with small datasets such as these:
    ——-
    – Select Database
    – This should be the only configuration you need
    USE Testing
    GO
    declare @Tables table (id integer identity(1,1),TName varchar(max))
    insert into @Tables (TName) SELECT Name FROM Sysobjects WHERE Type=’U’
    – Declare the @SQL Variable which will hold our dynamic sql
    DECLARE @SQL NVARCHAR(MAX);
    Declare @counter integer
    – Declare the @TblName Variable which will hold the name of the current table
    DECLARE @TblName NVARCHAR(MAX);
    SET @SQL = ”;
    select @counter = 1
    While @counter <= (select max(id) from @Tables)
    Begin–While Loop
    select @TblName = (select TName from @Tables where id = @Counter)
    – Appeand this table’s select count statement to our sql variable
    SET @SQL = @SQL + ‘ ( SELECT ”’+@TblName+”’ AS Table_Name,COUNT(*) AS Count FROM ‘+@TblName+’ ) UNION’;
    select @counter = @counter+1
    End–While Loop

    – Since we were adding the UNION at the end of each part, the last query will have
    – an extra UNION. Lets trim it off.
    SET @SQL = LEFT(@SQL,LEN(@SQL)-6);

    – Lets do an Order By. You can pick between Count and Table Name by picking which
    – line to execute below.
    SET @SQL = @SQL + ‘ ORDER BY Count’;
    –SET @SQL = @SQL + ‘ ORDER BY Table_Name’;

    – Now that our Dynamic SQL statement is ready, lets execute it.
    EXEC (@SQL);
    GO
    ——-

  2. try this
    use yourdatabasename

    SELECT name, rows FROM sysindexes where impid < 0 order by name

  3. Dos said

    The sysindexes query is fine but relies upon your database stats being up-to-date.

    Also I found that square brackets were needed around the tablename on line 26 – in the dynamic query (some of my tables begin with a numeric character)

    instead of:
    SET @SQL = @SQL + ‘ ( SELECT ”’+@TblName+”’ AS Table_Name,COUNT(*) AS Count FROM ‘+@TblName+’ ) UNION’

    use:
    SET @SQL = @SQL + ‘ ( SELECT ”’+@TblName+”’ AS Table_Name,COUNT(*) AS Count FROM ['+@TblName+'] ) UNION’

  4. Neal said

    Wouldn’t this be easier?!

    SELECT ‘select ”’+ name + ”’, count(*) from ‘ + name + ‘ union’
    FROM Sysobjects
    WHERE Type=’U’
    ORDER BY 1;

    Copy + paste the results, remove the trailing ‘union’ and add your ‘order by’ clause.

  5. Colin said

    Great post. Only issue I had was that my tables all use different schemas and not the default “dbo” schema, so I had to join to the sys.schemas table on schema_id and then concatenate the two columns from the sys.objects and sys.schemas tables together to get it to work.

    Quick question: Is there a way to list the row counts as well as the table sizes?

  6. Peter said

    Nice little post for this. I tweaked it for SQl Server 2000 and its limitation on varchar size. Left the cursor use in:

    – Create a cursor to loop through the System Ojects and get each table name
    DECLARE TBL_CURSOR CURSOR
    – Declare the SQL Statement to cursor through
    FOR (SELECT Name FROM Sysobjects WHERE Type=’U')

    – Declare the @SQL Variable which will hold our dynamic sql
    DECLARE @SQL VARCHAR(8000), @SQL2 VARCHAR(8000), @SQL3 VARCHAR(8000)
    SET @SQL = ”;
    SET @SQL2 = ”;
    SET @SQL3 = ”;
    – Declare the @TblName Variable which will hold the name of the current table
    DECLARE @TblName VARCHAR(255);

    – Open the Cursor
    OPEN TBL_CURSOR

    – Setup the Fetch While that will loop through our cursor and set @TblName
    FETCH NEXT FROM TBL_CURSOR INTO @TblName
    – Do this while we are not at the end of the record set
    WHILE (@@FETCH_STATUS -1)
    BEGIN
    – Appeand this table’s select count statement to our sql variable
    IF ASCII (@TblName) % 3 = 0
    SET @SQL = @SQL + ‘ ( SELECT ”’+@TblName+”’ AS Table_Name, COUNT(*) AS Count FROM ‘+@TblName+’ ) UNION’;

    IF ASCII (@TblName) % 3 = 1
    SET @SQL2 = @SQL2 + ‘ ( SELECT ”’+@TblName+”’ AS Table_Name, COUNT(*) AS Count FROM ‘+@TblName+’ ) UNION’;

    IF ASCII (@TblName) % 3 = 2
    SET @SQL3 = @SQL3 + ‘ ( SELECT ”’+@TblName+”’ AS Table_Name, COUNT(*) AS Count FROM ‘+@TblName+’ ) UNION’;

    – Pull the next record
    FETCH NEXT FROM TBL_CURSOR INTO @TblName
    – End the Cursor Loop
    END

    – Close and Clean Up the Cursor
    CLOSE TBL_CURSOR
    DEALLOCATE TBL_CURSOR

    – Since we were adding the UNION at the end of each part, the last query will have
    – an extra UNION. Lets trim it off.
    –SET @SQL = LEFT(@SQL, LEN(@SQL)-6);
    –SET @SQL2 = LEFT(@SQL2, LEN(@SQL2)-6);
    SET @SQL3 = LEFT(@SQL3, LEN(@SQL3)-6);

    – Lets do an Order By. You can pick between Count and Table Name by picking which
    – line to execute below.
    –SET @SQL = @SQL + ‘ ORDER BY Count’;
    –SET @SQL = @SQL + ‘ ORDER BY Table_Name’;

    – Now that our Dynamic SQL statement is ready, lets execute it.
    EXEC (@SQL + @SQL2 + @SQL3 + ‘ ORDER BY Count’);
    –EXEC (@SQL + @SQL2 + @SQL3 + ‘ ORDER BY Table_Name’);
    GO

  7. nausea said

    I used this:

    SELECT object_name(id) ,rowcnt
    FROM sysindexes
    WHERE indid IN (1,0) AND OBJECTPROPERTY(id, ‘IsUserTable’) = 1
    order by rowcnt desc

Some HTML is OK

(required)

(required, but never shared)

or, reply to this post via trackback.

Powered by WP Hashcash