Table size in the database - sql

I am new to SQL i know how to get the size of the database using
EXEC sp_spaceused
I have a question how can i get the size of a table in Sql Server database.
like Employee Table in the database.
Thanks In advance.

This slightly involved T-SQL statement will give you the exact same information that sp_spaceused returns:
WITH pages AS
(
SELECT
object_id,
SUM(reserved_page_count) AS reserved_pages,
SUM(used_page_count) AS used_pages,
SUM(CASE
WHEN (index_id < 2)
THEN (in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count)
ELSE lob_used_page_count + row_overflow_used_page_count
END) AS pages
FROM
sys.dm_db_partition_stats
GROUP BY
object_id),
extra AS
(
SELECT
p.object_id,
SUM(reserved_page_count) AS reserved_pages,
SUM(used_page_count) AS used_pages
FROM
sys.dm_db_partition_stats p
INNER JOIN
sys.internal_tables it ON p.object_id = it.object_id
WHERE
it.internal_type IN (202, 204, 211, 212, 213, 214, 215, 216)
GROUP BY
p.object_id)
SELECT
SchemaName = s.NAME,
TableName = t.NAME,
CompleteName = s.NAME + '.' + t.NAME,
(p.reserved_pages + ISNULL(e.reserved_pages, 0)) * 8 AS reserved_kb,
pages * 8 AS data_kb ,
(CASE
WHEN p.used_pages + ISNULL(e.used_pages, 0) > pages
THEN (p.used_pages + ISNULL(e.used_pages, 0) - pages)
ELSE 0
END) * 8 AS index_kb ,
(CASE
WHEN p.reserved_pages + ISNULL(e.reserved_pages, 0) > p.used_pages + ISNULL(e.used_pages, 0)
THEN (p.reserved_pages + ISNULL(e.reserved_pages, 0) - p.used_pages + ISNULL(e.used_pages, 0))
ELSE 0
END) * 8 AS unused_kb
FROM
pages p
INNER JOIN
sys.tables t ON t.object_id = p.object_id
INNER JOIN
sys.schemas s ON s.schema_id = t.schema_id
LEFT OUTER JOIN
extra e ON p.object_id = e.object_id
WHERE
t.is_ms_shipped = 0
ORDER BY
s.Name, t.Name
Of course, ideally, you'd "hide" this in a nicely useable stored procedure of your own to make it available whenever you need it ...

in mysql You can use this query to show the size of a table:
SELECT table_name AS "Table",
round(((data_length + index_length) / 1024 / 1024), 2) "Size in MB"
FROM information_schema.TABLES
WHERE table_schema = "$DB_NAME"
AND table_name = "$TABLE_NAME";
in sql:
sp_spaceused can get you information on the disk space used by a table, indexed view, or the whole database.
USE MyDatabase; GO
EXEC sp_spaceused N'dbo.MyTable'; GO
use this for all tables at once:
USE MyDatabase; GO
sp_msforeachtable 'EXEC sp_spaceused [?]' GO

One way is to look at the sys.dm_db_index_physical_stats output.
The min_record_size_in_bytes, max_record_size_in_bytes and avg_record_size_in_bytes will give you the sizes you want.
If you want to see the size of a particular record, another way is to find the physical row location, see
SQL Server 2008: New (undocumented) physical row locator function.
You can then dump the row physical structure, see Anatomy of a Record.

Related

Create a view in SQL with a row_count column [duplicate]

How to list row count of each table in the database. Some equivalent of
select count(*) from table1
select count(*) from table2
...
select count(*) from tableN
I will post a solution but other approaches are welcome
If you're using SQL Server 2005 and up, you can also use this:
SELECT
t.NAME AS TableName,
i.name as indexName,
p.[Rows],
sum(a.total_pages) as TotalPages,
sum(a.used_pages) as UsedPages,
sum(a.data_pages) as DataPages,
(sum(a.total_pages) * 8) / 1024 as TotalSpaceMB,
(sum(a.used_pages) * 8) / 1024 as UsedSpaceMB,
(sum(a.data_pages) * 8) / 1024 as DataSpaceMB
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
INNER JOIN
sys.allocation_units a ON p.partition_id = a.container_id
WHERE
t.NAME NOT LIKE 'dt%' AND
i.OBJECT_ID > 255 AND
i.index_id <= 1
GROUP BY
t.NAME, i.object_id, i.index_id, i.name, p.[Rows]
ORDER BY
object_name(i.object_id)
In my opinion, it's easier to handle than the sp_msforeachtable output.
A snippet I found at http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=21021 that helped me:
select t.name TableName, i.rows Records
from sysobjects t, sysindexes i
where t.xtype = 'U' and i.id = t.id and i.indid in (0,1)
order by TableName;
To get that information in SQL Management Studio, right click on the database, then select Reports --> Standard Reports --> Disk Usage by Table.
SELECT
T.NAME AS 'TABLE NAME',
P.[ROWS] AS 'NO OF ROWS'
FROM SYS.TABLES T
INNER JOIN SYS.PARTITIONS P ON T.OBJECT_ID=P.OBJECT_ID;
As seen here, this will return correct counts, where methods using the meta data tables will only return estimates.
CREATE PROCEDURE ListTableRowCounts
AS
BEGIN
SET NOCOUNT ON
CREATE TABLE #TableCounts
(
TableName VARCHAR(500),
CountOf INT
)
INSERT #TableCounts
EXEC sp_msForEachTable
'SELECT PARSENAME(''?'', 1),
COUNT(*) FROM ? WITH (NOLOCK)'
SELECT TableName , CountOf
FROM #TableCounts
ORDER BY TableName
DROP TABLE #TableCounts
END
GO
sp_MSForEachTable 'DECLARE #t AS VARCHAR(MAX);
SELECT #t = CAST(COUNT(1) as VARCHAR(MAX))
+ CHAR(9) + CHAR(9) + ''?'' FROM ? ; PRINT #t'
Output:
Well luckily SQL Server management studio gives you a hint on how to do this.
Do this,
start a SQL Server trace and open the activity you are doing (filter
by your login ID if you're not alone and set the application Name
to Microsoft SQL Server Management Studio), pause the trace and discard any results you have recorded till now;
Then, right click a table and select property from the pop up menu;
start the trace again;
Now in SQL Server Management studio select the storage property item on the left;
Pause the trace and have a look at what TSQL is generated by microsoft.
In the probably last query you will see a statement starting with exec sp_executesql N'SELECT
when you copy the executed code to visual studio you will notice that this code generates all the data the engineers at microsoft used to populate the property window.
when you make moderate modifications to that query you will get to something like this:
SELECT
SCHEMA_NAME(tbl.schema_id)+'.'+tbl.name as [table], --> something I added
p.partition_number AS [PartitionNumber],
prv.value AS [RightBoundaryValue],
fg.name AS [FileGroupName],
CAST(pf.boundary_value_on_right AS int) AS [RangeType],
CAST(p.rows AS float) AS [RowCount],
p.data_compression AS [DataCompression]
FROM sys.tables AS tbl
INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and idx.index_id < 2
INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int) AND p.index_id=idx.index_id
LEFT OUTER JOIN sys.destination_data_spaces AS dds ON dds.partition_scheme_id = idx.data_space_id and dds.destination_id = p.partition_number
LEFT OUTER JOIN sys.partition_schemes AS ps ON ps.data_space_id = idx.data_space_id
LEFT OUTER JOIN sys.partition_range_values AS prv ON prv.boundary_id = p.partition_number and prv.function_id = ps.function_id
LEFT OUTER JOIN sys.filegroups AS fg ON fg.data_space_id = dds.data_space_id or fg.data_space_id = idx.data_space_id
LEFT OUTER JOIN sys.partition_functions AS pf ON pf.function_id = prv.function_id
Now the query is not perfect and you could update it to meet other questions you might have, the point is, you can use the knowledge of microsoft to get to most of the questions you have by executing the data you're interested in and trace the TSQL generated using profiler.
I kind of like to think that MS engineers know how SQL server work and, it will generate TSQL that works on all items you can work with using the version on SSMS you are using so it's quite good on a large variety releases prerviouse, current and future.
And remember, don't just copy, try to understand it as well else you might end up with the wrong solution.
Walter
This approaches uses string concatenation to produce a statement with all tables and their counts dynamically, like the example(s) given in the original question:
SELECT COUNT(*) AS Count,'[dbo].[tbl1]' AS TableName FROM [dbo].[tbl1]
UNION ALL SELECT COUNT(*) AS Count,'[dbo].[tbl2]' AS TableName FROM [dbo].[tbl2]
UNION ALL SELECT...
Finally this is executed with EXEC:
DECLARE #cmd VARCHAR(MAX)=STUFF(
(
SELECT 'UNION ALL SELECT COUNT(*) AS Count,'''
+ QUOTENAME(t.TABLE_SCHEMA) + '.' + QUOTENAME(t.TABLE_NAME)
+ ''' AS TableName FROM ' + QUOTENAME(t.TABLE_SCHEMA) + '.' + QUOTENAME(t.TABLE_NAME)
FROM INFORMATION_SCHEMA.TABLES AS t
WHERE TABLE_TYPE='BASE TABLE'
FOR XML PATH('')
),1,10,'');
EXEC(#cmd);
The first thing that came to mind was to use sp_msForEachTable
exec sp_msforeachtable 'select count(*) from ?'
that does not list the table names though, so it can be extended to
exec sp_msforeachtable 'select parsename(''?'', 1), count(*) from ?'
The problem here is that if the database has more than 100 tables you will get the following error message:
The query has exceeded the maximum
number of result sets that can be
displayed in the results grid. Only
the first 100 result sets are
displayed in the grid.
So I ended up using table variable to store the results
declare #stats table (n sysname, c int)
insert into #stats
exec sp_msforeachtable 'select parsename(''?'', 1), count(*) from ?'
select
*
from #stats
order by c desc
Fastest way to find row count of all tables in SQL Refreence (http://www.codeproject.com/Tips/811017/Fastest-way-to-find-row-count-of-all-tables-in-SQL)
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
ORDER BY I.rows DESC
I want to share what's working for me
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
The database is hosted in Azure and the final result is:
Credit: https://www.mssqltips.com/sqlservertip/2537/sql-server-row-count-for-all-tables-in-a-database/
Here is my take on this question. It contains all schemas and lists only tables with rows. YMMV
select distinct schema_name(t.schema_id) as schema_name, t.name as
table_name, p.[Rows]
from sys.tables as t
INNER JOIN sys.indexes as 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 p.[Rows] > 0
order by schema_name;
If you use MySQL >4.x you can use this:
select TABLE_NAME, TABLE_ROWS from information_schema.TABLES where TABLE_SCHEMA="test";
Keep in mind that for some storage engines, TABLE_ROWS is an approximation.
The accepted answer didn't work for me on Azure SQL, here's one that did, it's super fast and did exactly what I wanted:
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 = 1
order by s.row_count desc
You could try this:
SELECT OBJECT_SCHEMA_NAME(ps.object_Id) AS [schemaname],
OBJECT_NAME(ps.object_id) AS [tablename],
row_count AS [rows]
FROM sys.dm_db_partition_stats ps
WHERE OBJECT_SCHEMA_NAME(ps.object_Id) <> 'sys' AND ps.index_id < 2
ORDER BY
OBJECT_SCHEMA_NAME(ps.object_Id),
OBJECT_NAME(ps.object_id)
This sql script gives the schema, table name and row count of each table in a database selected:
SELECT SCHEMA_NAME(schema_id) AS [SchemaName],
[Tables].name AS [TableName],
SUM([Partitions].[rows]) AS [TotalRowCount]
FROM sys.tables AS [Tables]
JOIN sys.partitions AS [Partitions]
ON [Tables].[object_id] = [Partitions].[object_id]
AND [Partitions].index_id IN ( 0, 1 )
-- WHERE [Tables].name = N'name of the table'
GROUP BY SCHEMA_NAME(schema_id), [Tables].name
order by [TotalRowCount] desc
Ref: https://blog.sqlauthority.com/2017/05/24/sql-server-find-row-count-every-table-database-efficiently/
Another way of doing this:
SELECT o.NAME TABLENAME,
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 i.rowcnt desc
I think that the shortest, fastest and simplest way would be:
SELECT
object_name(object_id) AS [Table],
SUM(row_count) AS [Count]
FROM
sys.dm_db_partition_stats
WHERE
--object_schema_name(object_id) = 'dbo' AND
index_id < 2
GROUP BY
object_id
USE DatabaseName
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
From this question:
https://dba.stackexchange.com/questions/114958/list-all-tables-from-all-user-databases/230411#230411
I added record count to the answer provided by #Aaron Bertrand that lists all databases and all tables.
DECLARE #src NVARCHAR(MAX), #sql NVARCHAR(MAX);
SELECT #sql = N'', #src = N' UNION ALL
SELECT ''$d'' as ''database'',
s.name COLLATE SQL_Latin1_General_CP1_CI_AI as ''schema'',
t.name COLLATE SQL_Latin1_General_CP1_CI_AI as ''table'' ,
ind.rows as record_count
FROM [$d].sys.schemas AS s
INNER JOIN [$d].sys.tables AS t ON s.[schema_id] = t.[schema_id]
INNER JOIN [$d].sys.sysindexes AS ind ON t.[object_id] = ind.[id]
where ind.indid < 2';
SELECT #sql = #sql + REPLACE(#src, '$d', name)
FROM sys.databases
WHERE database_id > 4
AND [state] = 0
AND HAS_DBACCESS(name) = 1;
SET #sql = STUFF(#sql, 1, 10, CHAR(13) + CHAR(10));
PRINT #sql;
--EXEC sys.sp_executesql #sql;
You can copy, past and execute this piece of code to get all table record counts into a table. Note: Code is commented with instructions
create procedure RowCountsPro
as
begin
--drop the table if exist on each exicution
IF OBJECT_ID (N'dbo.RowCounts', N'U') IS NOT NULL
DROP TABLE dbo.RowCounts;
-- creating new table
CREATE TABLE RowCounts
( [TableName] VARCHAR(150)
, [RowCount] INT
, [Reserved] NVARCHAR(50)
, [Data] NVARCHAR(50)
, [Index_Size] NVARCHAR(50)
, [UnUsed] NVARCHAR(50))
--inserting all records
INSERT INTO RowCounts([TableName], [RowCount],[Reserved],[Data],[Index_Size],[UnUsed])
-- "sp_MSforeachtable" System Procedure, 'sp_spaceused "?"' param to get records and resources used
EXEC sp_MSforeachtable 'sp_spaceused "?"'
-- selecting data and returning a table of data
SELECT [TableName], [RowCount],[Reserved],[Data],[Index_Size],[UnUsed]
FROM RowCounts
ORDER BY [TableName]
end
I have tested this code and it works fine on SQL Server 2014.
SELECT ( Schema_name(A.schema_id) + '.' + A.NAME ) AS TableName,
Sum(B.rows)AS RecordCount
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 ;
QUERY_PHOTO
QUERY_RESULT_PHOTO
Shnugo's answer is the ONLY one that works in Azure with Externa Tables. (1) Azure SQL doesn't support sp_MSforeachtable at all and (2) rows in sys.partitions for an External table is always 0.
select T.object_id, T.name, I.indid, I.rows
from Sys.tables T
left join Sys.sysindexes I
on (I.id = T.object_id and (indid =1 or indid =0 ))
where T.type='U'
Here indid=1 means a CLUSTERED index and indid=0 is a HEAP

Trying to create a table of table names and max values

In SQL Server, we have a number of tables, all containing a field last_modified that records when a particular record was created, modified, or flagged for deletion. I want to create a table of table names and the max() value of last_modified.
I'm brute forcing it as follows:
I run a query modified from Query to list number of records in each table in a database to list tables that have rows and eliminate some internal tables.
SELECT
t.NAME AS TableName,
p.[Rows]
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 t.name not like '%ml%' and
t.NAME not in ('OrderHeaders', 'OrderHeaderExtendedText', 'OrderLIDetails', 'OrderLIDetailExtendedText', 'UserCustomerXRef', 'UserDetails', 'UserDetailExtendedText', 'UserTypeDescription') and
p.rows <> 0 and
i.OBJECT_ID > 255 AND
i.index_id <= 1
GROUP BY
t.NAME, p.[Rows]
ORDER BY
TableName
This gives me a table like this:
Then I paste this output into Excel and create a series of queries there:
A2.value reads BidCustomerXRef. C2.Value reads ="select top 1 last_modified, '" & A2 & "' as 'Table' from " & A2 & " where deleted = 'N' order by last_modified desc" and so I get
select top 1 last_modified, 'BidCustomerXRef' as 'Table'
from BidCustomerXref
where deleted = 'N'
order by last_modified desc`
So I copy all of those rows to my SQL query window and I get this:
What I want is a single table that looks like this:
TableName
last_modified
BidCustomerXRef
2022-06-21 21:30:07.287
Bids
2022-06-22 20:00:06.383
CustomerARDetail
2022-06-22 18:00:11.923
etc.
Here is one way you can do this. I am using the system tables to generate dynamic sql instead of using a dreaded cursor or other sort of iteration going row by agonizing row.
declare #sql nvarchar(max) = ''
select #sql += 'select TableName = ''' + s.name + '.' + t.name + ''', last_modified = (select max(last_modified) from ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ' where deleted = ''N'') union all '
from sys.tables t
join sys.schemas s on s.schema_id = t.schema_id
join sys.indexes i ON t.object_id = i.object_id
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 t.name not like '%ml%'
and t.NAME not in ('OrderHeaders', 'OrderHeaderExtendedText', 'OrderLIDetails', 'OrderLIDetailExtendedText', 'UserCustomerXRef', 'UserDetails', 'UserDetailExtendedText', 'UserTypeDescription')
and p.rows > 0
and i.object_id > 255
and i.index_id <= 1
order by t.name
select #sql = left(#sql, len(#sql) - 9) --removes the last UNION ALL
select #sql
--uncomment the line below once you have evaluated that the dynamic sql is correct
--exec sp_executesql #sql

How to get all user defined datatypes in Sybase?

Could you please help me in finding all user defined datatypes in a sybase database.
Thanks!
Note: I realise this was asked a while ago, but I came across it looking for the answer, so thought I'd put it here.
The types are all in systypes, however they are not clearly delineated into user and system types. It seems that all the system types have accessrule set to NULL, and all my user types have this set to 0, so I've used the following:
SELECT * FROM systypes WHERE accessrule != NULL
This is good enough for what I'm doing.
You can see more about the systypes table (and other related tables) at:
http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.ase_15.0.tables/html/tables/tables69.htm
Since sybase is like SQL server using the profiler i got this query.
If it does not work, use a profiler like tool for sybase, create a user defined type, and check the system tables it updates.
SELECT
'Server[#Name=' + quotename(CAST(serverproperty(N'Servername') AS sysname),'''') + ']' + '/Database[#Name=' + quotename(db_name(),'''') + ']' + '/UserDefinedDataType[#Name=' + quotename(st.name,'''') + ' and #Schema=' + quotename(sst.name,'''') + ']' AS [Urn],
st.name AS [Name],
sst.name AS [Schema],
baset.name AS [SystemType],
CAST(CASE WHEN baset.name IN (N'nchar', N'nvarchar') AND st.max_length <> -1 THEN st.max_length/2 ELSE st.max_length END AS int) AS [Length],
CAST(st.precision AS int) AS [NumericPrecision],
CAST(st.scale AS int) AS [NumericScale],
st.is_nullable AS [Nullable]
FROM
sys.types AS st
INNER JOIN sys.schemas AS sst ON sst.schema_id = st.schema_id
LEFT OUTER JOIN sys.types AS baset ON baset.user_type_id = st.system_type_id and baset.user_type_id = baset.system_type_id
WHERE
(st.schema_id!=4 and st.system_type_id!=240 and st.user_type_id != st.system_type_id)
ORDER BY
[Schema] ASC,[Name] ASC
select
convert(char(15),a.name) [user type]
,(select convert(varchar(10),b.name)
from systypes b
where b.type=a.type
having b.usertype = min(b.usertype))
+ case
when (select b.name from systypes b
where b.type=a.type
having b.usertype = min(b.usertype) )='char'
then '('+convert(varchar(10),a.length)+')'
end
,a.prec
,a.scale
FROM systypes a
WHERE accessrule != NULL
go

How to find the size of a table in SQL?

How to find the size of a table in SQL?
SQL Server:-
sp_spaceused 'TableName'
Or in management studio:
Right Click on table -> Properties -> Storage
MySQL:-
SELECT table_schema, table_name, data_length, index_length FROM information_schema.tables
Sybase:-
sp_spaceused 'TableName'
Oracle:-
how-do-i-calculate-tables-size-in-oracle
Updating (after more than 10 years!) with an improved version using suggestions from the comments:
This gives you a list of all your tables in order of reserved size, ordered from largest to smallest.
This uses the same method as the previous one, but makes the results table a variable so it doesn't have to be cleaned up when done. Also it converts all the values to actual integers so they can be easily viewed and sorted.
DECLARE #tmpTableSizes TABLE
(
tableName VARCHAR(100),
numberofRows VARCHAR(100),
reservedSize VARCHAR(50),
dataSize VARCHAR(50),
indexSize VARCHAR(50),
unusedSize VARCHAR(50)
)
INSERT #tmpTableSizes
EXEC sp_MSforeachtable #command1="EXEC sp_spaceused '?'"
SELECT
tableName,
CAST(numberofRows AS INT) 'numberOfRows',
CAST(LEFT(reservedSize, LEN(reservedSize) - 3) AS INT) 'reservedSize KB',
CAST(LEFT(dataSize, LEN(dataSize) - 3) AS INT) 'dataSize KB',
CAST(LEFT(indexSize, LEN(indexSize) - 3) AS INT) 'indexSize KB',
CAST(LEFT(unusedSize, LEN(unusedSize) - 3) AS INT) 'unusedSize KB'
FROM
#tmpTableSizes
ORDER BY
[reservedSize KB] DESC
Previous Version before 2023-02-21:
Combining the answers from ratty's and Haim's posts (including comments) I've come up with this, which for SQL Server seems to be the most elegant so far:
-- DROP TABLE #tmpTableSizes
CREATE TABLE #tmpTableSizes
(
tableName varchar(100),
numberofRows varchar(100),
reservedSize varchar(50),
dataSize varchar(50),
indexSize varchar(50),
unusedSize varchar(50)
)
insert #tmpTableSizes
EXEC sp_MSforeachtable #command1="EXEC sp_spaceused '?'"
select * from #tmpTableSizes
order by cast(LEFT(reservedSize, LEN(reservedSize) - 4) as int) desc
This gives you a list of all your tables in order of reserved size, ordered from largest to smallest.
SQL Server provides a built-in stored procedure that you can run to easily show the size of a table, including the size of the indexes… which might surprise you.
Syntax:
sp_spaceused 'Tablename'
see in :
http://www.howtogeek.com/howto/database/determine-size-of-a-table-in-sql-server/
A query (modification of https://stackoverflow.com/a/7892349/1737819) to find a custom name table size in GB. You might try this, replace 'YourTableName' with the name of your table.
SELECT
t.NAME AS TableName,
p.rows AS RowCounts,
CONVERT(DECIMAL,SUM(a.total_pages)) * 8 / 1024 / 1024 AS TotalSpaceGB,
SUM(a.used_pages) * 8 / 1024 / 1024 AS UsedSpaceGB ,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 / 1024 / 1024 AS UnusedSpaceGB
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
INNER JOIN
sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN
sys.schemas s ON t.schema_id = s.schema_id
WHERE
t.NAME = 'YourTable'
AND t.is_ms_shipped = 0
AND i.OBJECT_ID > 255
GROUP BY
t.Name, s.Name, p.Rows
ORDER BY
UsedSpaceGB DESC, t.Name
Do you by size mean the number of records in the table, by any chance? In that case:
SELECT COUNT(*) FROM your_table_name
I know that in SQL 2012 (may work in other versions) you can do the following:
Right click on the database name in the Object Explorer.
Select Reports > Standard Reports > Disk Usage by Top Tables.
That will give you a list of the top 1000 tables and then you can order it by data size etc.
And in PostgreSQL:
SELECT pg_size_pretty(pg_relation_size('tablename'));
SQL Server, nicely formatted table for all tables in KB/MB:
SELECT
t.NAME AS TableName,
s.Name AS SchemaName,
p.rows AS RowCounts,
SUM(a.total_pages) * 8 AS TotalSpaceKB,
CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS TotalSpaceMB,
SUM(a.used_pages) * 8 AS UsedSpaceKB,
CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS UsedSpaceMB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB,
CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2) AS NUMERIC(36, 2)) AS UnusedSpaceMB
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
INNER JOIN
sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN
sys.schemas s ON t.schema_id = s.schema_id
WHERE
t.NAME NOT LIKE 'dt%'
AND t.is_ms_shipped = 0
AND i.OBJECT_ID > 255
GROUP BY
t.Name, s.Name, p.Rows
ORDER BY
t.Name
You may refer the answer by Marc_s in another thread, Very useful.
Get size of all tables in database
Here's a simple query, if you are just trying to find the largest tables.
-- Find largest table partitions
SELECT top 20 obj.name, LTRIM (STR ( sz.in_row_data_page_count * 8, 15, 0) + ' KB') as Size, * FROM sys.dm_db_partition_stats sz
inner join sys.objects obj on obj.object_id = sz.object_id
order by sz.in_row_data_page_count desc
In SQL Server run below query you will get table with size of table.
SELECT
CASE WHEN (GROUPING(sob.name)=1) THEN 'All_Tables'
ELSE ISNULL(sob.name, 'unknown') END AS TableName,
SUM(sys.length) AS ByteLength
FROM sysobjects sob, syscolumns sys
WHERE sob.xtype='u' AND sys.id = sob.id
GROUP BY sob.name
WITH CUBE
ORDER BY SUM(sys.length) DESC

SQLCMD.EXE generates ugly report. How to format it?

I did batch to run SQL query like
use [AxDWH_Central_Reporting]
GO
EXEC sp_spaceused #updateusage = N'TRUE'
GO
It displays 2 tables and generates some ugly report with some kind of 'P' unneeded letters... See below
Changed database context to 'AxDWH_Central_Reporting'.
database_name Pdatabase_size Punallocated space
--------------------------------------------------------------------------------------------------------------------------------P------------------P------------------
AxDWH_Central_Reporting P10485.69 MB P7436.85 MB
reserved Pdata Pindex_size Punused
------------------P------------------P------------------P------------------
3121176 KB P3111728 KB P7744 KB P1704 KB
----------------------------------------------------------------
I also tryed to generate 1 table from this procedure with next query
declare
#dbname sysname,
#dbsize bigint,
#logsize bigint,
#reservedpages bigint
select
#reservedpages = sum(a.total_pages)
from
sys.partitions p join sys.allocation_units a on p.partition_id = a.container_id left join sys.internal_tables it on p.object_id = it.object_id
select
#dbsize = sum(convert(bigint,case when status & 64 = 0 then size else 0 end)),
#logsize = sum(convert(bigint,case when status & 64 <> 0 then size else 0 end))
from
dbo.sysfiles
select
'database name' = db_name(),
'database size' = ltrim(str((convert (dec (15,2),#dbsize) + convert (dec (15,2),#logsize)) * 8192 / 1048576,15,2) + ' MB'),
'unallocated space' = ltrim(str((case when #dbsize >= #reservedpages then
(convert (dec (15,2),#dbsize) - convert (dec (15,2),#reservedpages)) * 8192 / 1048576 else 0 end),15,2) + ' MB')
But got similar ugly report:
database name Pdatabase size Punallocated space
--------------------------------------------------------------------------------------------------------------------------------P------------------P------------------
master P5.75 MB P1.52 MB
(1 rows affected)
Is it possible to change the layout formatting for report? To make it more beautifull?
I doubt you can get SQLCMD and sp_spaceused formatted nicely - why don't you just use some other means of getting the information you need?
In SQL Server 2005 and up, use this piece of T-SQL to display the tables and the size they use:
SELECT
t.NAME AS TableName,
i.name as indexName,
p.[Rows],
sum(a.total_pages) as TotalPages,
sum(a.used_pages) as UsedPages,
sum(a.data_pages) as DataPages,
(sum(a.total_pages) * 8) / 1024 as TotalSpaceMB,
(sum(a.used_pages) * 8) / 1024 as UsedSpaceMB,
(sum(a.data_pages) * 8) / 1024 as DataSpaceMB
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
INNER JOIN
sys.allocation_units a ON p.partition_id = a.container_id
WHERE
t.NAME NOT LIKE 'dt%' AND
i.OBJECT_ID > 255 AND
i.index_id <= 1
GROUP BY
t.NAME, i.object_id, i.index_id, i.name, p.[Rows]
ORDER BY
object_name(i.object_id)
Works just fine for me! :-)
Marc