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

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

Related

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 Find Table Space in SQL Server and in Oracle?

I have to find the table space of the table.
I tried sp_spaceused 'MyTableName'
But it is not Working. Are there any other ways?
In Oracle the tablespace name is contained in the dba_tables view.
select owner, tablespace_name
from dba_tables
where table_name = 'MyTableName'
Alternatively you can use the user_tables view to see the table name and TS name of only tables the current schema contains.
select table_name, tablespace_name
from user_tables
where table_name = 'MyTableName'
This should work fine for you As it works for me.
Solution refered from: How to find the total tablespace usage in SQL Server 2008? by Oleg Dok
set nocount on
declare #indexes table(
QualifiedName nvarchar(512),
IndexId int,
FGName nvarchar(128),
Type nvarchar(50),
NumKeys int,
IndexKB numeric(28,0),
UsedKB numeric(28,0),
FreeKB numeric(28,0),
Rows numeric(28,0),
RowModCtr numeric(28,0),
OrigFillFactor int,
tableid bigint
)
insert into #indexes
select
db_name() + '.' + isnull(su.name,'<unknown-user>') + '.' + so.name + '.' + isnull(i.name,'<Heap>') QualifiedName,
i.index_id IndexId,
(select isnull(name,'') from sys.filegroups where data_space_id = i.data_space_id) FGName,
case
when so.type = 'V' then 'Indexed View: '
else ''
end +
case
when i.index_id = 0 then 'Heap'
when i.index_id = 1 then 'Clustered'
else 'Non Clustered'
end Type,
0 NumKeys,
a.used_pages* 8 IndexKB,
CASE
When a.type <> 1 Then a.used_pages * 8
When p.index_id < 2 Then a.data_pages * 8
Else 0
END UsedKB,
(a.total_pages-a.used_pages)* 8 FreeKB,
p.rows Rows,
0 RowModCtr,
i.fill_factor OrigFillFactor,
convert(bigint,db_id()) * power(convert(bigint,2),48) + convert(bigint,su.schema_id) * power(convert(bigint,2),32) + so.object_id tableid
from
sys.objects so with (readpast)
inner join sys.schemas su with (readpast) on su.schema_id = so.schema_id
inner join sys.indexes i with (readpast) on so.object_id = i.object_id
inner join sys.partitions p with (readpast) ON i.object_id = p.object_id and i.index_id = p.index_id
inner join sys.allocation_units a with (readpast) on p.partition_id = a.container_id
where
(so.type = 'U') and a.type_Desc = 'IN_ROW_DATA'
and isnull(INDEXPROPERTY(i.object_id, i.name, 'IsStatistics'),0) = 0
and isnull(INDEXPROPERTY(i.object_id, i.name, 'IsAutoStatistics'),0) = 0
and isnull(INDEXPROPERTY(i.object_id, i.name, 'IsHypothetical'),0) = 0
order by
IndexKB desc
select
i.QualifiedName,
i.IndexId,
i.FGName,
i.Type,
i.NumKeys,
i.IndexKB,
(i.UsedKB - isnull(t.s_UsedKB,0)) UsedKB,
(i.FreeKB - isnull(t.s_FreeKB,0)) FreeKB,
i.Rows,
i.RowModCtr,
i.OrigFillFactor
from
#indexes i
left outer join (
select tableid, sum(UsedKB) s_UsedKB, sum(FreeKB) s_FreeKB
from #indexes
where IndexId > 1
group by tableid
) t on t.tableid = i.tableid
and i.IndexId <= 1
order by
IndexKB desc

Table size in the database

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.

How to find the total tablespace usage in SQL Server 2008?

In SQL-server 2008, How would I find (through an SQL query), the percentage of tablespace usage for a particular instance(or all instances) of a SQL Server(2008 R2)?
Also, what is the best way (query) to get the list of all the Named Instances of a SQL Server?
is this what you need:
EXEC sp_spaceused null, false
result:
database_name database_size unallocated space
--------------- ------------------ ------------------
DATABASE_NAME 220.25 MB 69.92 MB
reserved data index_size unused
------------------ ------------------ ------------------ ------------------
110672 KB 80368 KB 26944 KB 3360 KB
Use the script:
set nocount on
declare #indexes table(
QualifiedName nvarchar(512),
IndexId int,
FGName nvarchar(128),
Type nvarchar(50),
NumKeys int,
IndexKB numeric(28,0),
UsedKB numeric(28,0),
FreeKB numeric(28,0),
Rows numeric(28,0),
RowModCtr numeric(28,0),
OrigFillFactor int,
tableid bigint
)
insert into #indexes
select
db_name() + '.' + isnull(su.name,'<unknown-user>') + '.' + so.name + '.' + isnull(i.name,'<Heap>') QualifiedName,
i.index_id IndexId,
(select isnull(name,'') from sys.filegroups where data_space_id = i.data_space_id) FGName,
case
when so.type = 'V' then 'Indexed View: '
else ''
end +
case
when i.index_id = 0 then 'Heap'
when i.index_id = 1 then 'Clustered'
else 'Non Clustered'
end Type,
0 NumKeys,
a.used_pages* 8 IndexKB,
CASE
When a.type <> 1 Then a.used_pages * 8
When p.index_id < 2 Then a.data_pages * 8
Else 0
END UsedKB,
(a.total_pages-a.used_pages)* 8 FreeKB,
p.rows Rows,
0 RowModCtr,
i.fill_factor OrigFillFactor,
convert(bigint,db_id()) * power(convert(bigint,2),48) + convert(bigint,su.schema_id) * power(convert(bigint,2),32) + so.object_id tableid
from
sys.objects so with (readpast)
inner join sys.schemas su with (readpast) on su.schema_id = so.schema_id
inner join sys.indexes i with (readpast) on so.object_id = i.object_id
inner join sys.partitions p with (readpast) ON i.object_id = p.object_id and i.index_id = p.index_id
inner join sys.allocation_units a with (readpast) on p.partition_id = a.container_id
where
(so.type = 'U') and a.type_Desc = 'IN_ROW_DATA'
and isnull(INDEXPROPERTY(i.object_id, i.name, 'IsStatistics'),0) = 0
and isnull(INDEXPROPERTY(i.object_id, i.name, 'IsAutoStatistics'),0) = 0
and isnull(INDEXPROPERTY(i.object_id, i.name, 'IsHypothetical'),0) = 0
order by
IndexKB desc
select
i.QualifiedName,
i.IndexId,
i.FGName,
i.Type,
i.NumKeys,
i.IndexKB,
(i.UsedKB - isnull(t.s_UsedKB,0)) UsedKB,
(i.FreeKB - isnull(t.s_FreeKB,0)) FreeKB,
i.Rows,
i.RowModCtr,
i.OrigFillFactor
from
#indexes i
left outer join (
select tableid, sum(UsedKB) s_UsedKB, sum(FreeKB) s_FreeKB
from #indexes
where IndexId > 1
group by tableid
) t on t.tableid = i.tableid
and i.IndexId <= 1
order by
IndexKB desc

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