How to get a table storage information - sql-server

SQL Server Edition: SQL Server 2005 w/ SP3 and 2008
Is there a built-in SQL Server stored procedures that will retrieve following information?
Or a DMV (Dynamic Management View) would be great as well.
I am interested mainly on how to find out FILEGROUP data of a table specifically.
But it'd be better if there was a sproc that will return all of following result.
By the way, is there any documents that shows one-to-one matching of how to retrieve data that SQL Server UI displays?

The system stored procedure sp_help could be a good starting point.
For example:
exec sp_help 'schema.TableName'

This will show you all kinds of goodness:
-- Script to analyze table space usage using the
-- output from the sp_spaceused stored procedure
-- Works with SQL 7.0, 2000, and 2005
set nocount on
print 'Show Size, Space Used, Unused Space, Type, and Name of all database files'
select
[FileSizeMB] =
convert(numeric(10,2),sum(round(a.size/128.,2))),
[UsedSpaceMB] =
convert(numeric(10,2),sum(round(fileproperty( a.name,'SpaceUsed')/128.,2))) ,
[UnusedSpaceMB] =
convert(numeric(10,2),sum(round((a.size-fileproperty( a.name,'SpaceUsed'))/128.,2))) ,
[Type] =
case when a.groupid is null then '' when a.groupid = 0 then 'Log' else 'Data' end,
[DBFileName] = isnull(a.name,'*** Total for all files ***')
from
sysfiles a
group by
groupid,
a.name
with rollup
having
a.groupid is null or
a.name is not null
order by
case when a.groupid is null then 99 when a.groupid = 0 then 0 else 1 end,
a.groupid,
case when a.name is null then 99 else 0 end,
a.name
create table #TABLE_SPACE_WORK
(
TABLE_NAME sysname not null ,
TABLE_ROWS numeric(18,0) not null ,
RESERVED varchar(50) not null ,
DATA varchar(50) not null ,
INDEX_SIZE varchar(50) not null ,
UNUSED varchar(50) not null ,
)
create table #TABLE_SPACE_USED
(
Seq int not null
identity(1,1) primary key clustered,
TABLE_NAME sysname not null ,
TABLE_ROWS numeric(18,0) not null ,
RESERVED varchar(50) not null ,
DATA varchar(50) not null ,
INDEX_SIZE varchar(50) not null ,
UNUSED varchar(50) not null ,
)
create table #TABLE_SPACE
(
Seq int not null
identity(1,1) primary key clustered,
TABLE_NAME SYSNAME not null ,
TABLE_ROWS int not null ,
RESERVED int not null ,
DATA int not null ,
INDEX_SIZE int not null ,
UNUSED int not null ,
USED_MB numeric(18,4) not null,
USED_GB numeric(18,4) not null,
AVERAGE_BYTES_PER_ROW numeric(18,5) null,
AVERAGE_DATA_BYTES_PER_ROW numeric(18,5) null,
AVERAGE_INDEX_BYTES_PER_ROW numeric(18,5) null,
AVERAGE_UNUSED_BYTES_PER_ROW numeric(18,5) null,
)
declare #fetch_status int
declare #proc varchar(200)
select #proc = rtrim(db_name())+'.dbo.sp_spaceused'
declare Cur_Cursor cursor local
for
select
TABLE_NAME =
rtrim(TABLE_SCHEMA)+'.'+rtrim(TABLE_NAME)
from
INFORMATION_SCHEMA.TABLES
where
TABLE_TYPE = 'BASE TABLE'
order by
1
open Cur_Cursor
declare #TABLE_NAME varchar(200)
select #fetch_status = 0
while #fetch_status = 0
begin
fetch next from Cur_Cursor
into
#TABLE_NAME
select #fetch_status = ##fetch_status
if #fetch_status <> 0
begin
continue
end
truncate table #TABLE_SPACE_WORK
insert into #TABLE_SPACE_WORK
(
TABLE_NAME,
TABLE_ROWS,
RESERVED,
DATA,
INDEX_SIZE,
UNUSED
)
exec #proc #objname =
#TABLE_NAME ,#updateusage = 'true'
-- Needed to work with SQL 7
update #TABLE_SPACE_WORK
set
TABLE_NAME = #TABLE_NAME
insert into #TABLE_SPACE_USED
(
TABLE_NAME,
TABLE_ROWS,
RESERVED,
DATA,
INDEX_SIZE,
UNUSED
)
select
TABLE_NAME,
TABLE_ROWS,
RESERVED,
DATA,
INDEX_SIZE,
UNUSED
from
#TABLE_SPACE_WORK
end --While end
close Cur_Cursor
deallocate Cur_Cursor
insert into #TABLE_SPACE
(
TABLE_NAME,
TABLE_ROWS,
RESERVED,
DATA,
INDEX_SIZE,
UNUSED,
USED_MB,
USED_GB,
AVERAGE_BYTES_PER_ROW,
AVERAGE_DATA_BYTES_PER_ROW,
AVERAGE_INDEX_BYTES_PER_ROW,
AVERAGE_UNUSED_BYTES_PER_ROW
)
select
TABLE_NAME,
TABLE_ROWS,
RESERVED,
DATA,
INDEX_SIZE,
UNUSED,
USED_MB =
round(convert(numeric(25,10),RESERVED)/
convert(numeric(25,10),1024),4),
USED_GB =
round(convert(numeric(25,10),RESERVED)/
convert(numeric(25,10),1024*1024),4),
AVERAGE_BYTES_PER_ROW =
case
when TABLE_ROWS <> 0
then round(
(1024.000000*convert(numeric(25,10),RESERVED))/
convert(numeric(25,10),TABLE_ROWS),5)
else null
end,
AVERAGE_DATA_BYTES_PER_ROW =
case
when TABLE_ROWS <> 0
then round(
(1024.000000*convert(numeric(25,10),DATA))/
convert(numeric(25,10),TABLE_ROWS),5)
else null
end,
AVERAGE_INDEX_BYTES_PER_ROW =
case
when TABLE_ROWS <> 0
then round(
(1024.000000*convert(numeric(25,10),INDEX_SIZE))/
convert(numeric(25,10),TABLE_ROWS),5)
else null
end,
AVERAGE_UNUSED_BYTES_PER_ROW =
case
when TABLE_ROWS <> 0
then round(
(1024.000000*convert(numeric(25,10),UNUSED))/
convert(numeric(25,10),TABLE_ROWS),5)
else null
end
from
(
select
TABLE_NAME,
TABLE_ROWS,
RESERVED =
convert(int,rtrim(replace(RESERVED,'KB',''))),
DATA =
convert(int,rtrim(replace(DATA,'KB',''))),
INDEX_SIZE =
convert(int,rtrim(replace(INDEX_SIZE,'KB',''))),
UNUSED =
convert(int,rtrim(replace(UNUSED,'KB','')))
from
#TABLE_SPACE_USED aa
) a
order by
TABLE_NAME
print 'Show results in descending order by size in MB'
select * from #TABLE_SPACE order by USED_MB desc
go
drop table #TABLE_SPACE_WORK
drop table #TABLE_SPACE_USED
drop table #TABLE_SPACE

Found a solution.
It seems like it takes longer to type this out than using UI to find out table FILEGROUP information.
Found through List tables in filegroups:
declare #objectid bigint
set #objectid = object_id('table_name')
exec sp_objectfilegroup #objectid
I became too lazy to type those three lines so ended up creating another stored procedure that takes table name instead.
create procedure spTableFileGroup
#TableName sysname
as
begin
if exists( select 1
from INFORMATION_SCHEMA.TABLES T
where T.TABLE_NAME = #TableName) begin
declare #objectid bigint
set #objectid = object_id(#TableName)
exec sp_objectfilegroup #objectid
end
else begin
print 'There is no table named "' + #TableName + '"'
end
end
GO
Usage
exec spTableFileGroup 'table_name'
GO

Have a look at DBCC showfilestats or sp_spaceused for filegroups.
Found a script at a blog. That lists tables and their sizes.
For a more user friendly (administrative view, you can generate reports using right mouse on the db).

The tables FILEGROUP is determined by it's clustered index. You can use this query to find the filegroup:
SELECT *
FROM
sys.tables AS tbl
INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and idx.index_id < 2
LEFT OUTER JOIN sys.data_spaces AS dsidx ON dsidx.data_space_id = idx.data_space_id
In regard to your second question, I don't think there's any documentation, however, you can use SQL profiler when you view the details in SSMS. This will show you the exact queries.

This might do the trick ->
use Your_database_name
GO
SELECT FG.*, MF.* FROM sys.filegroups FG INNER JOIN sys.master_files
MF on MF.data_space_id = FG.data_space_id WHERE database_id = db_id()

Related

Select on a table with 2 possible structures

I'm trying to write a query that will select data from a table. due to different versions of the database, there are 2 possible structures for the source table, where the newer version has 2 more fields than the old one.
I've tried identifying the older structure and replacing the columns with NULL and also tried writing 2 separate queries with and IF statement directing to the correct one. Neither of these solutions work and in both cases it seems that the SQL engine is failing on validating these 2 columns.
Examples of my attempted solutions:
IF NOT EXISTS (SELECT *
FROM sys.objects
WHERE object_id = Object_id(N'[dbo].[Test2]')
AND type IN ( N'U' ))
BEGIN
CREATE TABLE [dbo].[test2]
(
[id] [INT] IDENTITY(1, 1) NOT NULL,
[statusid] [INT] NULL
)
END
go
DECLARE #Flag INT = 0
IF EXISTS(SELECT 1
FROM sys.columns
WHERE NAME = N'TestId'
AND object_id = Object_id(N'dbo.Test2'))
SET #Flag = 1
--Solution #1
IF #Flag = 1
SELECT id,
statusid,
testid
FROM dbo.test2
ELSE
SELECT id,
statusid
FROM dbo.test2
--Solution #2
SELECT id,
statusid,
CASE
WHEN #Flag = 1 THEN testid
ELSE NULL
END AS TestId
FROM dbo.test2
you can use Dynamic SQL and generate the query accordingly depends on value of #flag
declare #sql nvarchar(max)
select #sql = N'select id, statusid, '
+ case when #flag = 1 then 'testid' else 'NULL' end + ' as testid'
+ ' from dbo.test2'
print #sql
exec sp_executesql #sql
But it will not be that easy to code and maintain Dynamic Query if you have a complex query.

query/script/stored procedure which will return a single table

I have the following query. can someone help rapping this in a cursor.
IF OBJECT_ID('tempdb.[dbo].[#Results]') IS NOT NULL
DROP TABLE [dbo].[#Results]
GO
CREATE TABLE [dbo].[#Results] (
[DatabaseName] VARCHAR(128) NULL,
[DatabaseVersion] VARCHAR(128) NULL,
[DateChangedOn] DATETIME NULL)
EXEC sp_msForEachDb '
IF EXISTS (SELECT * FROM [?].sys.objects WHERE NAME = ''stdVersions'')
BEGIN
INSERT INTO #Results
SELECT
''?'' AS [DatabaseName],
v.[DatabaseVersion],
l.[DateChangedOn]
FROM [?].dbo.stdVersions v
CROSS JOIN [?].dbo.stdChangeLog l
END'
SELECT * FROM #Results ORDER BY DateChangedOn
the query should return list of all database names in the server and within the databases return the databaseversion column and DateChangeOn Column. All the databases in the server contain tables named stdVersions and stdChangeLog of which the stdVersion table have a single row of DatabaseVersion comes and stdChangeLog table have a single row of DateChangedOn.
Below is an example of creating a cursor on the #Results table.
DECLARE #DatabaseName sysname
, #DatabaseVersion sysname
, #DateChangedOn datetime;
DECLARE DatabaseList CURSOR LOCAL FAST_FORWARD
FOR
SELECT DatabaseName
, DatabaseVersion
, DateChangedOn
FROM #Results
ORDER BY DateChangedOn;
OPEN DatabaseList;
WHILE 1 = 1
BEGIN
FETCH NEXT FROM DatabaseList INTO
#DatabaseName
, #DatabaseVersion
, #DateChangedOn;
IF ##FETCH_STATUS = -1 BREAK;
--process row here
END;
CLOSE DatabaseList;
DEALLOCATE DatabaseList;
You mention that the "std" tables exist in all databases. If these tables does not include system databases, change the IF statement in the script below to exclude those:
IF EXISTS (SELECT * FROM [?].sys.objects WHERE NAME = ''stdVersions'')
AND [?] NOT IN(N'master', N'model', N'tempdb', N'msdb', N'SSISDB')

Sybase ASE identify columns of keys of multiple tables

I'm trying to identify the columns making up keys in ASE.
Sybase has the solution listed here: http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.help.ase.15.5/title.htm
I have a slightly modified version below, however it only works (just as sybase's solution) if I look up for a single table, but I want to use the 'in' keyword and look up all the tables in one shot.
Could I get some help, as to why the solution below does not work? It only generates the list of columns for 't5' table.
declare #keycnt integer
declare #objname varchar(256)
select #keycnt = keycnt, #objname = sysobjects.name from sysindexes, sysobjects
where
--sysobjects.id = object_id("t5")
--sysobjects.id = object_id("t4")
sysobjects.id in (object_id("t5"), object_id("t4"))
and sysobjects.id = sysindexes.id
and indid = 1
while #keycnt > 0
begin
select index_col(#objname, 1, #keycnt)
select #keycnt = #keycnt - 1
end
These are the tables I'm using for testing:
CREATE TABLE t4(
[value] [varchar] (500) not NULL ,
CONSTRAINT pk_g4 PRIMARY KEY CLUSTERED (
[value]
)
)
CREATE TABLE t5(
[myvalue] [varchar] (500) not NULL ,
CONSTRAINT pk_g4 PRIMARY KEY CLUSTERED (
[myvalue]
)
)
You have two solutions:
Using OR
declare #keycnt integer
declare #objname varchar(256)
select #keycnt = keycnt, #objname = sysobjects.name from sysindexes, sysobjects
where
--sysobjects.id = object_id("t5")
--sysobjects.id = object_id("t4")
(sysobjects.id = object_id("t5") OR sysobjects.id = object_id("t4"))
and sysobjects.id = sysindexes.id
and indid = 1
while #keycnt > 0
begin
select index_col(#objname, 1, #keycnt)
select #keycnt = #keycnt - 1
end
Or Using Dynamic SQL to properly use the IN.

SQL-Server Trigger on update for Audit

I can't find an easy/generic way to register to an audit table the columns changed on some tables.
I tried to do it using a Trigger on after update in this way:
First of all the Audit Table definition:
CREATE TABLE [Audit](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Date] [datetime] NOT NULL default GETDATE(),
[IdTypeAudit] [int] NOT NULL, --2 for Modify
[UserName] [varchar](50) NULL,
[TableName] [varchar](50) NOT NULL,
[ColumnName] [varchar](50) NULL,
[OldData] [varchar](50) NULL,
[NewData] [varchar](50) NULL )
Next a trigger on AFTER UPDATE in any table:
DECLARE
#sql varchar(8000),
#col int,
#colcount int
select #colcount = count(*) from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'MyTable'
set #col = 1
while(#col < #colcount )
begin
set #sql=
'INSERT INTO Audit
SELECT 2, UserNameLastModif, ''MyTable'', COL_NAME(Object_id(''MyTable''), '+ convert(varchar,#col) +'), Deleted.'
+ COL_NAME(Object_id('MyTable'), #col) + ', Inserted.' + COL_NAME(Object_id('MyTable'), #col) + '
FROM Inserted LEFT JOIN Deleted ON Inserted.[MyTableId] = Deleted.[MyTableId]
WHERE COALESCE(Deleted.' + COL_NAME(Object_id('MyTable'), #col) + ', '''') <> COALESCE(Inserted.' + COL_NAME(Object_id('MyTable'), #col) + ', '''')'
--UserNameLastModif is an optional column on MyTable
exec(#sql)
set #col = #col + 1
end
The problems
Inserted and Deleted lost the context when I use the exec function
Seems that colnumber it isn't always a correlative number, seems if you create a table with 20 columns and you delete one and create another, the last one have a number > #colcount
I was looking for a solution for all over the net but I couln't figure out
Any Idea?
Thanks!
This highlights a greater problem with structural choice. Try to write a set-based solution. Remove the loop and dynamic SQL and write a single statement that inserts the Audit rows. It is possible but to make it easier consider a different table layout, like keeping all columns on 1 row instead of splitting them.
In SQL 2000 use syscolumns. In SQL 2005+ use sys.columns. i.e.
SELECT column_id FROM sys.columns WHERE object_id = OBJECT_ID(DB_NAME()+'.dbo.Table');
#Santiago : If you still want to write it in dynamic SQL, you should prepare all of the statements first then execute them.
8000 characters may not be enough for all the statements. A good solution is to use a table to store them.
IF NOT OBJECT_ID('tempdb..#stmt') IS NULL
DROP TABLE #stmt;
CREATE TABLE #stmt (ID int NOT NULL IDENTITY(1,1), SQL varchar(8000) NOT NULL);
Then replace the line exec(#sql) with INSERT INTO #stmt (SQL) VALUES (#sql);
Then exec each row.
WHILE EXISTS (SELECT TOP 1 * FROM #stmt)
BEGIN
BEGIN TRANSACTION;
EXEC (SELECT TOP 1 SQL FROM #stmt ORDER BY ID);
DELETE FROM #stmt WHERE ID = (SELECT MIN(ID) FROM #stmt);
COMMIT TRANSACTION;
END
Remember to use sys.columns for the column loop (I shall assume you use SQL 2005/2008).
SET #col = 0;
WHILE EXISTS (SELECT TOP 1 * FROM sys.columns WHERE object_id = OBJECT_ID('MyTable') AND column_id > #col)
BEGIN
SELECT TOP 1 #col = column_id FROM sys.columns
WHERE object_id = OBJECT_ID('MyTable') AND column_id > #col ORDER BY column_id ASC;
SET #sql ....
INSERT INTO #stmt ....
END
Remove line 4 #colcount int and the proceeding comma. Remove Information schema select.
DO not ever use any kind of looping a trigger. Do not use dynamic SQl or call a stored proc or send an email.All of these things are exretemly inappropriate in a trigger.
If tyou want to use dynamic sql use it to create the script to create the trigger. And create an audit table for every table you want audited (we actually have two for every table) or you will have performance problems due to locking on the "one table to rule them all".

Is there any way to find out the size / sizes of your database tables?

i've got around 10 tables in my sql 2008 server.
Currently, my mdf is around 3.5Gig. (I also have some binary data in some of the tables). So, I'm wondering if there's a way i could see which tables are the biggest in size.
Is this possible?
Maybe it's an index or FTS catalog instead?
run this:
/******************************************************************************
** File: “GetTableSpaceUseage.sql”
** Name: Get Table Space Useage for a specific schema
** Auth: Robert C. Cain
** Date: 01/27/2008
**
** Desc: Calls the sp_spaceused proc for each table in a schema and returns
** the Table Name, Number of Rows, and space used for each table.
**
** Called by:
** n/a – As needed
**
** Input Parameters:
** In the code check the value of #schemaname, if you need it for a
** schema other than dbo be sure to change it.
**
** Output Parameters:
** NA
*******************************************************************************/
/*—————————————————————————*/
/* Drop the temp table if it's there from a previous run */
/*—————————————————————————*/
if object_id(N'tempdb..[#TableSizes]') is not null
drop table #TableSizes ;
go
/*—————————————————————————*/
/* Create the temp table */
/*—————————————————————————*/
create table #TableSizes
(
[Table Name] nvarchar(128) /* Name of the table */
, [Number of Rows] char(11) /* Number of rows existing in the table. */
, [Reserved Space] varchar(18) /* Reserved space for table. */
, [Data Space] varchar(18) /* Amount of space used by data in table. */
, [Index Size] varchar(18) /* Amount of space used by indexes in table. */
, [Unused Space] varchar(18) /* Amount of space reserved but not used. */
) ;
go
/*—————————————————————————*/
/* Load the temp table */
/*—————————————————————————*/
declare #schemaname varchar(256) ;
-- Make sure to set next line to the Schema name you want!
set #schemaname = 'dbo' ;
-- Create a cursor to cycle through the names of each table in the schema
declare curSchemaTable cursor
for select sys.schemas.name + '.' + sys.objects.name
from sys.objects
, sys.schemas
where object_id > 100
and sys.schemas.name = #schemaname
/* For a specific table uncomment next line and supply name */
--and sys.objects.name = 'specific-table-name-here'
and type_desc = 'USER_TABLE'
and sys.objects.schema_id = sys.schemas.schema_id ;
open curSchemaTable ;
declare #name varchar(256) ; /* This holds the name of the current table*/
-- Now loop thru the cursor, calling the sp_spaceused for each table
fetch curSchemaTable into #name ;
while ( ##FETCH_STATUS = 0 )
begin
insert into #TableSizes
exec sp_spaceused #objname = #name ;
fetch curSchemaTable into #name ;
end
/* Important to both close and deallocate! */
close curSchemaTable ;
deallocate curSchemaTable ;
/*—————————————————————————*/
/* Feed the results back */
/*—————————————————————————*/
select [Table Name]
, [Number of Rows]
, [Reserved Space]
, [Data Space]
, [Index Size]
, [Unused Space]
from [#TableSizes]
order by [Table Name] ;
/*—————————————————————————*/
/* Remove the temp table */
/*—————————————————————————*/
drop table #TableSizes ;
taken from Robert Caine blog
Edited the code to parse, several chars that were in single quote used a special single quote, as well the -- sign.
This code is for Microsoft SQL 2005+
exec sp_spaceused [tablename]
sys.allocations_units has the information you need. You join with sys.partitions to group all allocation units of a partition together and also to obtain the more usable object_id rather than the esoteric allocation_unit_id.
select object_name(p.object_id),
sum(au.total_pages)*8 as [space_in_kb]
from sys.partitions p
join sys.allocation_units au on p.hobt_id = au.container_id
group by p.object_id
order by [space_in_kb] desc
And yes, all tables (heap or clustered) are 'partitions', the terms does not refer to partitioned tables. sys.partitions also has the 'rows' column that may interest you.
exec sp_spaceused <tablename>
This query shows the size of each table in the current database.
SELECT sysobjects.[name] AS [TableName],
SUM(sysindexes.reserved) * 8 AS [Size(KB)],
SUM(sysindexes.dpages) * 8 AS [Data(KB)],
(SUM(sysindexes.used) - SUM(sysindexes.dpages)) * 8 AS [Indexes(KB)],
(SUM(sysindexes.reserved) - SUM(sysindexes.dpages)) * 8 AS [Unused(KB)]
FROM dbo.sysindexes AS sysindexes
JOIN dbo.sysobjects AS sysobjects ON sysobjects.id = sysindexes.id
WHERE sysobjects.[type] = 'U'
GROUP BY sysobjects.[name]
ORDER BY [Size(KB)] DESC
In SQL 2008+: right-click on the DB name in SSMS, select Reports, then Standard Reports, then Disk Usage by Table.
Sometimes I run this... It gets all tables to temp table, loops it through and gets sizes for all tables. Result data is in #tablesizes, so you can query it how you like.
Works in Sql Server >2005
declare #tables TABLE
(
table_name nvarchar(200)
)
declare #tablesizes TABLE
(
[name] nvarchar(200),
[rows] int,
reserved nvarchar(200),
data nvarchar(200),
index_size nvarchar(200),
unused nvarchar(200),
reserved_int int,
data_int int,
index_size_int int,
unused_int int
)
declare #t nvarchar(200)
insert into #tables
select Table_Name from information_schema.tables
while exists(select * from #tables)
begin
set #t=(select top 1 table_name from #tables)
insert into #tablesizes([name],[rows],reserved,data,index_size,unused)
exec sp_spaceused #t
delete top (1) from #tables
end
update #tablesizes set
reserved_int=convert(int, replace(reserved,' KB','')),
data_int=convert(int, replace(data,' KB','')),
index_size_int=convert(int, replace(index_size,' KB','')),
unused_int=convert(int, replace(unused,' KB',''))
select * from #tablesizes order by data_int desc
You could 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 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;

Resources