How can I get all table names, row counts and their data sizes in a SQL Server 2012 database? - sql

I need to analyze my database. I want to get all table names, their record counts and actual data size of these tables. As you know, record count sometimes may be low but actual size of table can be very high.
Do you have such a script?

Will this work for you? It's a script I use:
SELECT
S.name +'.'+ T.name as TableName,
Convert(varchar,Cast(SUM(P.rows) as Money),1) as [RowCount],
Convert(varchar,Cast(SUM(a.total_pages) * 8 as Money),1) AS TotalSpaceKB,
Convert(varchar,Cast(SUM(a.used_pages) * 8 as Money),1) AS UsedSpaceKB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM sys.tables T
INNER JOIN sys.partitions P ON P.OBJECT_ID = T.OBJECT_ID
INNER JOIN sys.schemas S ON T.schema_id = S.schema_id
INNER JOIN sys.allocation_units A ON p.partition_id = a.container_id
WHERE T.is_ms_shipped = 0 AND P.index_id IN (1,0)
GROUP BY S.name, T.name
ORDER BY SUM(P.rows) DESC
By the way, I cast the counts as money so I can get commas.

Another method using CURSOR and temp table.
IF OBJECT_ID(N'tempdb..[#TableSizes]') IS NOT NULL
DROP TABLE #TableSizes ;
GO
CREATE TABLE #TableSizes
(
TableName nvarchar(128)
, [RowCount] int
, ReservedSpaceKB int
, DataSpaceKB int
, IndexSizeKB int
, UnusedSpaceKB int
) ;
GO
DECLARE RecCountCursor CURSOR FOR
SELECT S.name+'.'+T.name AS TableName
FROM Sys.tables T INNER JOIN sys.schemas S ON (S.schema_id = T.schema_id)
WHERE S.principal_id = 1
ORDER BY TableName
OPEN RecCountCursor ;
DECLARE #TableName nvarchar(128) ;
FETCH RecCountCursor INTO #TableName ;
WHILE ( ##FETCH_STATUS = 0 )
BEGIN
CREATE TABLE #TempTableSizes
(
[TableName] nvarchar(128)
, [RowCount] char(11)
, [ReservedSpace] varchar(18)
, [DataSpace] varchar(18)
, [IndexSize] varchar(18)
, [UnusedSpace] varchar(18)
) ;
INSERT INTO #TempTableSizes
exec sp_spaceused #objname = #TableName;
UPDATE #TempTableSizes SET [TableName] = #TableName;
INSERT INTO #TableSizes
SELECT [TableName], [RowCount],
SUBSTRING([ReservedSpace], 1, CHARINDEX(' KB', [ReservedSpace])),
SUBSTRING([DataSpace], 1, CHARINDEX(' KB', [DataSpace])),
SUBSTRING([IndexSize], 1, CHARINDEX(' KB', [IndexSize])),
SUBSTRING([UnusedSpace], 1, CHARINDEX(' KB', [UnusedSpace]))
FROM #TempTableSizes
DROP TABLE #TempTableSizes;
FETCH RecCountCursor INTO #TableName ;
end
CLOSE RecCountCursor ;
DEALLOCATE RecCountCursor ;
SELECT *
FROM [#TableSizes]
ORDER BY [ReservedSpaceKB] DESC ;
DROP TABLE #TableSizes ;

Use:
SELECT ##servername;
IF EXISTS(SELECT name FROM tempdb.sys.tables WHERE name LIKE '#spaceUsed%')
BEGIN
DROP TABLE #spaceUsed;
END;
CREATE TABLE #spaceUsed (
name VARCHAR(255) ,
rows INT ,
reserved VARCHAR(50) ,
data VARCHAR(50) ,
index_size VARCHAR(50) ,
unused VARCHAR(50));
EXEC sp_msforeachtable
#command1 ='
--
INSERT INTO #spaceUsed
exec sp_spaceused N''?'';
'
,#whereand = ' And Object_id In (Select Object_id From sys.objects
Where SCHEMA_NAME(Schema_ID) like ''%'')';
DECLARE
#spaceUsedData TABLE (
name VARCHAR(255) ,
rows INT ,
reservedMB BIGINT NULL ,
dataMB BIGINT NULL ,
index_sizeMB BIGINT NULL ,
unusedMB BIGINT NULL);
INSERT INTO #spaceUsedData (name , rows , reservedMB , dataMB ,index_sizeMB ,unusedMB)
SELECT name , rows ,
Convert ( BIGINT ,Ltrim(Rtrim(Replace(reserved ,'KB' ,'')) ))/1024 ,
Convert ( BIGINT ,Ltrim(Rtrim(Replace(data ,'KB' ,'')) ))/1024 ,
Convert ( BIGINT ,Ltrim(Rtrim(Replace(index_size ,'KB' ,'')) ))/1024 ,
Convert ( BIGINT ,Ltrim(Rtrim(Replace(unused ,'KB' ,'')) ))/1024
FROM #spaceUsed;
SELECT * , reservedMB+ dataMB+index_sizeMB+unusedMB AS TotalMB FROM #spaceUsedData
ORDER BY rows DESC;

Related

Count rows in all tables, that meets conditions

I have database with 7,000 tables, most of these have a column DataAreaId, but not all tables, since some are global.
I would like to list all tables that have the column DataAreaId and their row count where the column DataAreaId contains "FR".
So for one table it would be:
SELECT COUNT(*)
FROM Table
WHERE DataAreaId = 'FR'
Any suggestions?
You can use the following
CREATE TABLE T1(
Dataareaid VARCHAR(45)
);
CREATE TABLE T2(
Dataareaid VARCHAR(45)
);
INSERT INTO T1 VALUES
('FR'),
('ALG'),
('FR');
DECLARE #SQL NVARCHAR(max) = N'';
SELECT #SQL = (
SELECT CONCAT(
N'UNION ALL ',
N'SELECT ''',
t.name,
N''' AS TableName, ',
N'Cnt = (SELECT COUNT(1)',
' FROM ',
QUOTENAME(t.name),
N' WHERE [Dataareaid] = ''FR'')'
)
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE c.name = 'Dataareaid'
FOR XML PATH('')
)
SET #SQL = STUFF(#SQL, 1, 10, N'');
EXEC sp_executesql #SQL;
Returns:
+-----------+-----+
| TableName | Cnt |
+-----------+-----+
| T1 | 2 |
| T2 | 0 |
+-----------+-----+
Live Demo
One way to do this is to query all tables containing that column, and build a query statement for each
select 'union all select ' + QUOTENAME(t.name,N'''') + ', count(1) from ' + t.name + ' where Dataareaid = ''FR'''
from sys.columns c
join sys.tables t ON c.object_id = t.object_id
where c.name = 'Dataareaid'
each row would look like this
union all select 'SomeTable', count(1) from SomeTable where Dataareaid = 'FR'
Now just put all statements together and remove the first union all
My answer gets the column metadata, executes the statement in a loop and publishes the results to a table variable:
if object_id('tempdb..#LoopList') is not null
drop table #LoopList
select
s.[name] as SchemaName
,t.[name] as TableName
,row_number() over (order by t.[object_id] asc) as RowNumber
into #LoopList
from sys.columns as c
inner join sys.tables as t
on c.[object_id] = t.[object_id]
inner join sys.schemas as s
on t.[schema_id] = s.[schema_id]
where c.[name] = 'Dataareaid'
declare
#a int = 1
,#b int = (select max(RowNumber) from #LoopList)
,#c nvarchar(max)
,#d nvarchar(max)
,#e int
declare #count table (RowCounter int)
declare #resultsTable table (TableName nvarchar(500), RowCounter int)
while #a <= #b
begin
delete from #count
set #c = concat ((select quotename(SchemaName) from #LoopList where RowNumber = #a)
,'.'
,(select quotename(TableName) from #LoopList where RowNumber = #a)
)
set #d = concat(N'select count(*) from '
,#c
,N' where Dataareaid = ''FR'''
)
insert into #count (
RowCounter
)
exec sp_executesql #d
set #e = (select top 1 RowCounter from #count)
insert into #resultsTable (
TableName
,RowCounter
)
values (#c,#e)
set #a += 1;
end
select * from #resultsTable

Query tables ordered by having most number of records

i have a task to cleanup the database from useless records. in the planning, first i have to check what are the tables that holds the most number of records. i know i can check them one by one manually, but the table list is too long and am thinking it's not too wise to run through them manually before checking if there is any automatic query that can do the job.
manually, i can query each table using this query:
select count(*) from <table_name>
even using sysobjects, i could not find the current Number Of Records
select * from sysobjects s where type='U' and name = '<table_name>'
anybody has an idea?
An approximation for the number of rows in each table is kept as part of index statistics, and is stored in the yourDB..systabstats Assuming you run update statistics on a regular basis, here's how you can get the information.
SELECT o.name, t.rowcnt
FROM sysobjects o, systabstats t
WHERE o.id = t.id
AND t.rowcnt > 0 --ignore 0 row entries
AND o.name not like "sys%" --exclude system tables
ORDER BY t.rowcnt DESC
This works in T-SQL. Not sure if it will work in Sybase...
CREATE TABLE #RecCounts (TableName varchar(100), RecCount int)
SELECT object_id INTO #Processed FROM sys.tables WHERE name = '(no such table)'
DECLARE #TableId int, #TableName varchar(255), #TableSchema varchar(100), #CountSQL varchar(255)
SELECT #TableId = MIN(object_id) FROM sys.tables WHERE type = 'U'
AND object_id NOT IN (SELECT object_id FROM #Processed)
SET #TableId = ISNULL(#TableId, -1)
WHILE #TableId > -1 BEGIN
PRINT #TableId
SELECT #TableName = name FROM sys.tables WHERE type = 'U' AND object_id = #TableId
SELECT #TableSchema = s.name, #TableName = t.name
FROM sys.Tables t
INNER JOIN sys.schemas s ON s.schema_id = t.schema_id
WHERE t.object_id = #TableId
SET #CountSQL = 'DECLARE #RecCount int
SELECT #RecCount = COUNT(*) FROM ' + #TableSchema + '.' + #TableName + '
INSERT INTO #RecCounts (TableName, RecCount) VALUES (''' + #TableName + ''', #RecCount)'
PRINT #CountSQL
EXEC(#CountSQL)
INSERT INTO #Processed (object_id) VALUES(#TableId)
SELECT #TableId = MIN(object_id) FROM sys.tables WHERE type = 'U'
AND object_id NOT IN (SELECT object_id FROM #Processed)
END
SELECT * FROM #RecCounts

Use Probability for a field in a database is in the set (6, 12, 24)

I want to find all the fields in a database where 80% or more of the values are in the set (6,12,24).
Can I use sys.tables to do this with sys.columns to build a join to then look inside of each field for the probabilty?
Example for were this might apply is in the following list:
6 - Half a Dozen
12 - A Dozen
24 - Two Dozen
So the table would look something like this in procedural language:
select all the tables names in sys.tables and look in each number column in sys.columns for that table where 80% of the values are in the set (6,12,24).
Cribbing from my approach on this answer
https://stackoverflow.com/questions/20156747/number-of-null-values-for-every-column-on-ssis/20156981#20156981
You're going to need to look at a similar approach. Here I am using the system metadata to discover what columns are whole numbers (if you need to account for floating point numbers, factor that into the first filter).
SET NOCOUNT ON;
DECLARE
-- actual query
#query nvarchar(max)
-- templated query
, #template nvarchar(max);
-- Return column & schema/table combo anywhere
-- there is data in the column that starts like the
-- search key.
SELECT
#template = N'
SELECT COUNT(1) AS rc
, ''<COLUMN_NAME/>'' AS cname
, ''<SCHEMA/>.<TABLE_NAME/>'' AS tname
FROM
<SCHEMA/>.<TABLE_NAME/> T
WHERE
T.<COLUMN_NAME/> IN (6, 12, 24)';
DECLARE
CSR CURSOR
FOR
-- Iterate through all the columns
SELECT
ISC.TABLE_SCHEMA
, ISC.TABLE_NAME
, ISC.COLUMN_NAME
, ISC.IS_NULLABLE
FROM
INFORMATION_SCHEMA.COLUMNS ISC
WHERE
(
ISC.DATA_TYPE IN ('bigint', 'int', 'smallint', 'tinyint')
);
-- Cursor variables for capturing candidate schemas, tables and columns
DECLARE
#table_schema sysname
, #table_name sysname
, #column_name sysname
, #nullable varchar(3);
DECLARE
#RESULTS TABLE
(
instance_count bigint NOT NULL
, column_name sysname NOT NULL
, table_schema nvarchar(500) NOT NULL
);
OPEN
CSR;
FETCH NEXT
FROM
CSR
INTO
#table_schema
, #table_name
, #column_name
, #nullable;
WHILE (##FETCH_STATUS = 0)
BEGIN
-- stub in actual names, make 'em safe via quotename function
SET #query = REPLACE(#template, '<SCHEMA/>', quotename(#table_schema));
SET #query = REPLACE(#query, '<TABLE_NAME/>', quotename(#table_name));
SET #query = REPLACE(#query, '<COLUMN_NAME/>', quotename(#column_name));
BEGIN TRY
-- Dump results into a table variable
INSERT INTO
#RESULTS
EXECUTE(#query);
END TRY
BEGIN CATCH
-- print failing query
PRINT #query;
END CATCH
FETCH NEXT
FROM
CSR
INTO
#table_schema
, #table_name
, #column_name
, #nullable;
END
CLOSE CSR;
DEALLOCATE CSR;
WITH ROW_COUNTS AS
(
SELECT
s.[Name] as table_schema
, t.[name] as table_name
, SUM(p.rows) as TotalRowCount
FROM
sys.schemas s
LEFT OUTER JOIN
sys.tables t
ON s.schema_id = t.schema_id
LEFT OUTER JOIN
sys.partitions p
ON t.object_id = p.object_id
LEFT OUTER JOIN
sys.allocation_units a
ON p.partition_id = a.container_id
WHERE
p.index_id in(0,1) -- 0 heap table , 1 table with clustered index
AND p.rows is not null
AND a.type = 1 -- row-data only , not LOB
GROUP BY
s.[Name]
, t.[name]
)
SELECT
RC.table_schema
, RC.table_name
, R.column_name
, R.instance_count
, RC.TotalRowCount
-- ensure we don't divide by zero and perform floating division
, CAST(R.instance_count / (NULLIF(RC.TotalRowCount, 0) * 1.0) AS decimal(18,2)) AS InstancePercentage
FROM
ROW_COUNTS AS RC
INNER JOIN
#results R
ON R.table_schema = quotename(RC.table_schema) + '.' + quotename(table_name)
WHERE
CAST(R.instance_count / (NULLIF(RC.TotalRowCount, 0) * 1.0) AS decimal(18,2)) > .8;
If you drop the filter, then you'll see the percent of values found. It currently NULLs out the percentage for tables with zero rows.

How to generate temp table columns and datatypes automatically via script

I create temp tables quite often in SQL and I am looking into a way to generate the column names and datatypes automatically for the table definition so I don't have to look them all up everytime.
For example I run:
SELECT CustomerID
ClientID,
FirstName
LastName
INTO #Test
From dbo.Customer
To initially setup the temp table with the appropriate columns and data I need. Once I get that all done, I then go back in and take out the INTO statement and write the following:
CREATE TABLE #Test
(
...
...
);
I want to find a way to auto generate the column names and datatypes from the initial creation of the temp table. Right now, since I am initially inserting into an automatically created temp table, I use this:
EXEC tempdb..sp_help '#Test';
This gives me everything I need without having to look all the column datatypes up, but I wanted to know if there was a way to just auto gen the column names off of something like this. So the auto gen would generate:
CustomerID int,
ClientID int,
FirstName varchar(50),
LastName varchar(50)
This would allow me to just copy and paste this into my create table statement.
this might give you a start:
DECLARE #viewname VARCHAR(50);
SET #viewname ='tableorviewname';
SELECT c.name + ' '+ t.name +
case t.name
WHEN 'varchar' THEN '('+CAST(c.max_length AS VARCHAR(3) )+'),'
ELSE ','
end
FROM sys.columns c
INNER JOIN sys.types AS t ON c.system_type_id = t.system_type_id
WHERE object_id = (SELECT object_id from sys.objects where name = #viewname)
ORDER BY c.column_id
EDIT: TEMP TABLES:
temp tables are slightly different, for instance this works in sql 2008 for a temp table named #tv_source
DECLARE #viewortablename VARCHAR(50);
SET #viewortablename ='tempdb..#tv_source';
SELECT c.name + ' '+ t.name +
case t.name
WHEN 'varchar' THEN '('+CAST(c.max_length AS VARCHAR(3) )+'),'
ELSE ','
end
FROM tempdb.sys.columns c
INNER JOIN sys.types AS t ON c.system_type_id = t.system_type_id
WHERE object_id = object_id(#viewortablename)
ORDER BY c.column_id
NOTES: this gives a comma separated list, but did NOT attempt to remove that last comma, it gives only a list, which you would likely want to put on a string and manipulate, etc. then use as a dynamic sql or somthing. Still, it should give you a start on what you wish to do.
NOTE for to others, sql 2000 would not display the lengths properly for instance on a varchar(45), it would just list the varchar part and I did not attempt to rework that for this question.
SELECT
', ['+ac.name+'] '+Type_Name(User_type_id)+
CASE WHEN Type_Name(User_type_id) = 'Decimal'
THEN +'('+CONVERT(Varchar(4),ac.Precision)+','+CONVERT(Varchar(4),ac.Scale)+')'
WHEN Type_Name(User_type_id) IN
('tinyint','smallint','int','real','money','float','numeric','smallmoney','DateTime')
THEN ''
ELSE +'('+CONVERT(Varchar(4),ac.Max_Length)+')'
END AS TableColumn
FROM Tempdb.sys.all_columns AS ac
INNER JOIN Tempdb.Sys.SysObjects AS so
ON so.ID = ac.Object_ID
WHERE 1 = 1
AND so.Name = '##YourTempTableGoesHere'
...I've created a function that can output the list of columns and datatypes, if the object is a table, if that is something that would be useful for you?
CREATE FUNCTION [dbo].[fnDiscoverColumns]
( #PObjectName NVARCHAR(300) )
RETURNS #Data TABLE ( ColumnList NVARCHAR(350) )
AS
BEGIN
DECLARE #PObjectID TABLE ( [object_id] INT )
INSERT #PObjectID ( [object_id] )
SELECT [object_id] FROM sys.objects AS O WHERE O.name = #PObjectName AND O.type = 'U'
DECLARE #PObjectDetails TABLE ( [RowNo] INT,[ColumnName] NVARCHAR(300),[XType] INT,[DataType] NVARCHAR(100),[system_type_id] INT,[user_type_id] INT,[MaxLength] NVARCHAR(5),[Precision] INT,[Scale] INT,[ColumnList] NVARCHAR(300) )
INSERT #PObjectDetails ( [RowNo],[ColumnName],[XType],[DataType],[system_type_id],[user_type_id],[MaxLength],[Precision],[Scale],[ColumnList] )
SELECT DISTINCT
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS 'RowNo',
C.name AS 'ColumnName',
T.xtype AS 'XType',
UPPER(T.name) AS 'DataType',
C.system_type_id,
C.user_type_id,
CASE WHEN C.max_length < 0 THEN 'MAX' ELSE CAST(C.max_length AS VARCHAR) END AS 'MaxLength',
C.precision AS 'Precision',
C.scale AS 'Scale',
CASE
WHEN [XType] IN (34,35,36,40,48,52,56,58,59,60,61,62,98,99,104,122,127,189,240,241) THEN QUOTENAME(C.name) +' '+ UPPER(T.name) +','
WHEN [XType] IN (106,108) THEN QUOTENAME(C.name) +' '+ UPPER(T.name) +'('+ CAST([Precision] AS VARCHAR) +','+ CAST(C.scale AS VARCHAR) +'),'
WHEN [XType] IN (41,42,43,165,167,173,175,231,239) THEN QUOTENAME(C.name) +' '+ UPPER(T.name) +'('+ CASE WHEN C.max_length < 0 THEN 'MAX' WHEN C.max_length > 1 THEN CAST(C.max_length / 2 AS VARCHAR) ELSE CAST(C.max_length AS VARCHAR) END +'),' ELSE NULL END AS 'ColumnList'
FROM sys.all_columns AS C
JOIN systypes AS T ON C.system_type_id = T.xusertype
WHERE C.object_id = (SELECT * FROM #PObjectID) --373576369
--Return column names and data types
INSERT #Data
SELECT 'CREATE TABLE #ColumnsList ('
INSERT #Data
SELECT
CASE WHEN C.RowNo = (SELECT MAX(RowNo) FROM #PObjectDetails) THEN LEFT(C.ColumnList, ABS(LEN(C.ColumnList + ',') - 2)) ELSE C.ColumnList END AS 'GeneratedColumns'
FROM #PObjectDetails AS C
INSERT #Data
SELECT ')'
RETURN
END
GO
Once committed to the database, run it like this:
SELECT * FROM [dbo].[fnDiscoverColumns] ('ExecutionLogStorage') --name of table
This should give you an output like this:
CREATE TABLE #ColumnsList (
[LogEntryId] BIGINT,
[InstanceName] NVARCHAR(38),
[ReportID] UNIQUEIDENTIFIER,
[UserName] NVARCHAR(260),
[ExecutionId] NVARCHAR(64),
[RequestType] TINYINT,
[Format] NVARCHAR(26),
[Parameters] NTEXT,
[ReportAction] TINYINT,
[TimeStart] DATETIME,
[TimeEnd] DATETIME,
[TimeDataRetrieval] INT,
[TimeProcessing] INT,
[TimeRendering] INT,
[Source] TINYINT,
[Status] NVARCHAR(40),
[ByteCount] BIGINT,
[RowCount] BIGINT,
[AdditionalInfo] XML
)

SQL 2005 - Query to Find Tables with Most Rows

I searched for this for a while but came up empty ... hopefully someone here can help.
Is there a query I can run on a database (SQL Server 2005) that will return the number of rows in each table?
You could try something like this:
SELECT
[TableName] = so.name,
[RowCount] = MAX(si.rows)
FROM
sysobjects so,
sysindexes si
WHERE
so.xtype = 'U'
AND
si.id = OBJECT_ID(so.name)
GROUP BY
so.name
ORDER BY
2 DESC
Galwegian got it almost right :-) For SQL Server 2005 and up, I always recommed using the "sys.*" system views instead of the (soon to be deprecated) sysobjects and sysindexes tables.
SELECT
t.NAME AS 'Table Name',
SUM(p.[Rows]) as 'Row Count'
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
WHERE
t.NAME NOT LIKE 'dt%' AND
i.OBJECT_ID > 255 AND
i.index_id = 1
GROUP BY
t.NAME
ORDER BY
SUM(p.[Rows]) DESC
Marc
here's my version which uses a dm_db_partition_stats DMV:
SELECT object_name(object_id) as table_name,
SUM (row_count) AS total_number_of_rows
FROM sys.dm_db_partition_stats
WHERE (index_id=0 or index_id=1)
group by object_name(object_id)
order by SUM (row_count) desc
this will return row_count, col_count, data_size
enjoy!.
http://blog.sqlauthority.com/2007/01/10/sql-server-query-to-find-number-rows-columns-bytesize-for-each-table-in-the-current-database-find-biggest-table-in-database/
I don't remember where I got this, I'm pretty sure I didn't write it and it's definitely overkill but it's still fun.
USE master
GO
SET NOCOUNT ON
DECLARE #EnumDBs TABLE ([id] INT IDENTITY, [sql] VARCHAR(1024), PRIMARY KEY ([id]))
CREATE TABLE #EnumTables ([id] INT IDENTITY, [db] SYSNAME, [owner] SYSNAME, [table] SYSNAME, PRIMARY KEY ([db], [owner], [table], [id]))
CREATE TABLE #TableMetrics ([id] INT IDENTITY, [db] SYSNAME NULL, [table] SYSNAME, [rows] INT, [reserved] VARCHAR(256), [data] VARCHAR(256), [index_size] VARCHAR(256), [unused] VARCHAR(256), PRIMARY KEY ([table], [id]))
DECLARE #i INT
DECLARE #sql VARCHAR(1024)
DECLARE #db SYSNAME
INSERT INTO #EnumDBs
SELECT ' USE ['+name+']
DBCC UPDATEUSAGE(0) WITH NO_INFOMSGS
INSERT INTO #EnumTables
SELECT '''+name+''' AS [db]
, u.name AS [owner]
, o.name AS [table]
FROM sysobjects AS o
JOIN sysusers AS u
ON o.uid = u.uid
WHERE type = ''U''
ORDER BY u.name
, o.name' AS [sql]
FROM master.dbo.sysdatabases WITH (NOLOCK)
WHERE dbid > 4
SELECT #i=COUNT(*)
, #sql=''
FROM #EnumDBs
WHILE #i > 0
BEGIN
SELECT #sql = SQL
FROM #EnumDBs
WHERE ID = #i
IF ##ROWCOUNT > 0
EXEC(#sql)
IF (##ERROR <> 0) GOTO ERR_HANDLER
SET #i=#i-1
END
SELECT #i=COUNT(*)
, #sql=''
FROM #EnumTables
WHILE #i > 0
BEGIN
SELECT #db=[db]
, #sql='USE ['+[db]+'] EXEC SP_SPACEUSED ''['+[db]+'].['+[owner]+'].['+[table]+']'''
FROM #EnumTables
WHERE ID = #i
--PRINT #SQL
INSERT INTO #TableMetrics
([table], [rows], [reserved], [data], [index_size], [unused])
EXEC(#sql)
IF (##ERROR <> 0) GOTO ERR_HANDLER
UPDATE #TableMetrics
SET [db]=#db
WHERE [db] IS NULL
IF (##ERROR <> 0) GOTO ERR_HANDLER
SET #i=#i-1
END
SELECT * FROM #TableMetrics ORDER BY [db], CAST(REPLACE([reserved],' KB','') AS INT) DESC
ERR_HANDLER:
DROP TABLE #EnumTables
DROP TABLE #TableMetrics
try this:
create table:
create table maxRows (tablename varchar(900) primary key,CountOf int)
run this and copy the output:
EXEC sp_msforeachtable 'print ''INSERT INTO maxRows SELECT ''''?'''', COUNT(*) FROM ? WITH (NOLOCK)'''
run the copied output, it inserts into the table a row count for each table
now run this, lists the tables with their row count:
select countOf,tablename from maxRows order by CountOf DESC
When run in a database, the following returns table row counts and index/total space usage.
declare #tableName varchar(100);
create table
#table
(
tablename sysname,
row_count int,
reserved varchar(50),
data varchar(50),
index_size varchar(50),
unused varchar(50)
);
create table
#table2
(
tableName varchar(100),
row_count int,
data_size int,
index_size int,
reserved int,
unused int
);
declare C_T cursor fast_forward for
select TableName = '[' + s.name + '].[' + t.name + ']'
from sys.tables t
inner join sys.schemas s on t.schema_id = s.schema_id
where t.type = 'U'
order by s.name,
t.name;
open C_T;
fetch next from C_T into #tableName;
while ##FETCH_STATUS = 0
begin
truncate table #table;
insert into #table
exec sp_spaceused #tableName, false;
insert into #table2(tableName, row_count, data_size, index_size, reserved, unused)
select #tableName,
row_count,
convert(int, replace(data, ' KB', '')),
convert(int, replace(index_size, ' KB', '')),
convert(int, replace(reserved, ' KB', '')),
convert(int, replace(unused, ' KB', ''))
from #table;
fetch next from C_T into #tableName;
end
close C_T;
deallocate C_T;
select [Table Name] = tableName,
[Rows] = row_count,
[Data Size (KB)] = data_size,
[Indexes Size (KB)] = index_size,
[Reserved Space (KB)] = reserved,
[Unused Space (KB)] = unused
from #table2
order by data_size desc;
drop table #table;
drop table #table2;