cross database query only works one way MS SQL Server - sql

I am attempting to insert data about index usage into a control database of sorts.. The query I am using is below.. the issue I have is that when I execute the query from the control database (lets call it A) it returns 0 results, but if I execute it from the source database (lets call that B) it runs just fine..
why?
This behavior is being seen on both SQL Server 2012 DEV and SQL Server 2008 EE.
Example 1 returns zero results:
USE A;
INSERT INTO A.dbo.UnusedIndexes
SELECT 
DB_NAME() AS DatabaseName
, SCHEMA_NAME(o.Schema_ID) AS SchemaName
, OBJECT_NAME(o.object_id) AS TableName
, ix.name AS IndexName
,((SUM(ps.used_page_count)over(partition by ix.index_id))*8)/1024 AS [IndexSizeMB]
, ix_usage_stats.user_updates
, ix_usage_stats.user_seeks + ix_usage_stats.user_scans + ix_usage_stats.user_lookups
AS [User_SeeksScansLookups]
    , ix_usage_stats.system_updates
, ix_usage_stats.system_seeks + ix_usage_stats.system_scans + ix_usage_stats.system_lookups
AS [System_SeeksScansLookups]
, NULL as [Drop_Statement]
, NULL as [Create_statement]
,getdate() as [date_added]
FROM B.sys.indexes ix
Left join B.sys.dm_db_index_usage_stats ix_usage_stats
 ON ix_usage_stats.object_id = ix.object_id
AND ix_usage_stats.index_id = ix.index_id
INNER JOIN B.sys.objects o ON ix.object_id = o.object_id
JOIN B.sys.dm_db_partition_stats ps ON ps.object_id = ix.object_id AND ix.index_id = ps.index_id
WHERE 
ix.name IS NOT NULL -- exclude heaps
AND ix.type <> 1 -- exclude the clustered indexes
AND o.is_ms_shipped = 0 -- exclude system objects
AND o.type NOT IN('F', 'UQ') -- exclude the foreign keys and unique contraints
AND SCHEMA_NAME(o.schema_id) not in ('dbo','stats', 'reporting') 
AND (ix_usage_stats.user_seeks = 0 or ix_usage_stats.user_seeks is NULL)
AND (ix_usage_stats.user_scans = 0 or ix_usage_stats.user_scans is null)
AND (ix_usage_stats.user_lookups = 0 or ix_usage_stats.user_lookups is null)
Example 2 returns the expected results, populating A.dbo.UnusedIndexes:
USE B;
INSERT INTO A.dbo.UnusedIndexes
SELECT
DB_NAME() AS DatabaseName
, SCHEMA_NAME(o.Schema_ID) AS SchemaName
, OBJECT_NAME(o.object_id) AS TableName
, ix.name AS IndexName
,((SUM(ps.used_page_count)over(partition by ix.index_id))*8)/1024 AS [IndexSizeMB]
, ix_usage_stats.user_updates
, ix_usage_stats.user_seeks + ix_usage_stats.user_scans + ix_usage_stats.user_lookups
AS [User_SeeksScansLookups]
, ix_usage_stats.system_updates
, ix_usage_stats.system_seeks + ix_usage_stats.system_scans + ix_usage_stats.system_lookups
AS [System_SeeksScansLookups]
, NULL as [Drop_Statement]
, NULL as [Create_statement]
,getdate() as [date_added]
FROM B.sys.indexes ix
Left join B.sys.dm_db_index_usage_stats ix_usage_stats
ON ix_usage_stats.object_id = ix.object_id
AND ix_usage_stats.index_id = ix.index_id
INNER JOIN B.sys.objects o ON ix.object_id = o.object_id
JOIN B.sys.dm_db_partition_stats ps ON ps.object_id = ix.object_id AND ix.index_id = ps.index_id
WHERE
ix.name IS NOT NULL -- exclude heaps
AND ix.type <> 1 -- exclude the clustered indexes
AND o.is_ms_shipped = 0 -- exclude system objects
AND o.type NOT IN('F', 'UQ') -- exclude the foreign keys and unique contraints
AND SCHEMA_NAME(o.schema_id) not in ('dbo','stats', 'reporting')
AND (ix_usage_stats.user_seeks = 0 or ix_usage_stats.user_seeks is NULL)
AND (ix_usage_stats.user_scans = 0 or ix_usage_stats.user_scans is null)
AND (ix_usage_stats.user_lookups = 0 or ix_usage_stats.user_lookups is null)
This works all day long:
USE A;
Select * from B.sys.indexes
Any help would be great - and unfortunately I am unable to execute this from database B, so the easy solution won't work.
Solved
Figured it out. the DB_NAME() was the issue. removing that and setting it to 'B' as databasename fixed the issue.

Try using sp_executesql from the target database:
USE A;
INSERT INTO A.dbo.UnusedIndexes
EXEC B.sys.sp_executesql N'
SELECT DB_NAME() AS DatabaseName
,SCHEMA_NAME(o.Schema_ID) AS SchemaName
,OBJECT_NAME(o.object_id) AS TableName
,ix.NAME AS IndexName
,((SUM(ps.used_page_count) OVER (PARTITION BY ix.index_id)) * 8) / 1024 AS [IndexSizeMB]
,ix_usage_stats.user_updates
,ix_usage_stats.user_seeks + ix_usage_stats.user_scans + ix_usage_stats.user_lookups AS [User_SeeksScansLookups]
,ix_usage_stats.system_updates
,ix_usage_stats.system_seeks + ix_usage_stats.system_scans + ix_usage_stats.system_lookups AS [System_SeeksScansLookups]
,NULL AS [Drop_Statement]
,NULL AS [Create_statement]
,getdate() AS [date_added]
FROM sys.indexes ix
LEFT JOIN sys.dm_db_index_usage_stats ix_usage_stats
ON ix_usage_stats.object_id = ix.object_id
AND ix_usage_stats.index_id = ix.index_id
INNER JOIN sys.objects o
ON ix.object_id = o.object_id
JOIN sys.dm_db_partition_stats ps
ON ps.object_id = ix.object_id
AND ix.index_id = ps.index_id
WHERE 1 = 1
AND ix.name IS NOT NULL -- exclude heaps
AND ix.type <> 1 -- exclude the clustered indexes
AND o.is_ms_shipped = 0 -- exclude system objects
AND o.type NOT IN(''F'', ''UQ'') -- exclude the foreign keys and unique contraints
AND SCHEMA_NAME(o.schema_id) not in (''dbo'',''stats'', ''reporting'')
AND (
ix_usage_stats.user_seeks = 0
OR ix_usage_stats.user_seeks IS NULL
)
AND (
ix_usage_stats.user_scans = 0
OR ix_usage_stats.user_scans IS NULL
)
AND (
ix_usage_stats.user_lookups = 0
OR ix_usage_stats.user_lookups IS NULL
)
'

Related

How to locate the default value constraint for a column name

I noticed that some date columns in a database table are giving my Power App a hard time ( patching) when the default value is '0001-01-01' and the no valid date is supplied. Note I can't just set default values in my Power App as the SQL Table is used by other applications.
My current thinking is I change the default value say to '1001-01-01' using TSQL so that I can automate it as much as possible.
Get the (DF_TABLENAME_XXXX) constraint name for the column and say shove it into a variable #mytablename
Drop this constraint name
Recreate the constraint with
ALTER TABLE #MyTable DEFAULT '1001-12-31' FOR #ColumnName
I am struggling with step 1) atm . Also I am happy to adopt a better approach than the one I have outlined.
I wrote this code sometime ago to create a Data Dictionary of sorts. It uses all the sys tables to grab information about the tables in your database. Just change the top line and you should be all set.
USE [INSERT YOUR DATABASE NAME HERE]
GO
SELECT
DB_NAME() AS [DatabaseName]
, OBJECT_SCHEMA_NAME(TBL.[object_id],DB_ID()) AS [Schema]
, TBL.[name] AS [TableName]
, AC.[name] AS [ColumnName]
, UPPER(TY.[name]) AS [DataType]
, AC.[max_length] AS [Length]
, AC.[precision] AS [Precision]
, AC.[scale] AS [Scale]
, AC.[is_nullable] AS [IsNullable]
, ISNULL(SI.is_primary_key,0) AS [IsPrimaryKey]
, SKC.name AS [PrimaryKeyConstarint]
, CASE
WHEN SIC.index_column_id > 0
THEN 1
ELSE 0
END AS [IsIndexed]
, ISNULL(is_included_column, 0) AS [IsIncludedIndex]
, SI.name AS [IndexName]
, OBJECT_NAME(SFC.constraint_object_id) AS [ForeignKeyConstraint]
, OBJECT_SCHEMA_NAME(TBL_PRIM.[object_id],DB_ID()) AS [ParentTableSchema]
, OBJECT_NAME(SFC.referenced_object_id) AS [ParentTableName]
, COL_PRIM.name AS [ParentTableColumnName]
, OBJECT_SCHEMA_NAME(TBL.[object_id],DB_ID()) + '.' + TBL.[name] + '.' + AC.[name]
+ ' = ' + OBJECT_SCHEMA_NAME(TBL_PRIM.[object_id],DB_ID()) + '.'
+ OBJECT_NAME(SFC.referenced_object_id) + '.' + COL_PRIM.name AS [JoinCondition]
, SDC.name AS [DefaultConstraint]
, SDC.[definition] AS [DefaultValue]
, AC.collation_name AS [Collation]
, SEP.value AS [Comments]
FROM [sys].[tables] AS TBL
JOIN [sys].[all_columns] AS AC
ON TBL.[object_id] = AC.[object_id]
JOIN [sys].[types] AS TY
ON AC.[system_type_id] = TY.[system_type_id]
AND AC.[user_type_id] = TY.[user_type_id]
LEFT JOIN [sys].[index_columns] AS SIC
ON sic.[object_id] = TBL.[object_id]
AND AC.column_id = SIC.column_id
LEFT JOIN [sys].[indexes] AS SI
ON SI.[object_id] = TBL.[object_id]
AND SIC.index_id = SI.index_id
LEFT JOIN [sys].[foreign_key_columns] AS SFC
ON SFC.parent_object_id = TBL.[object_id]
AND SFC.parent_column_id = AC.column_id
LEFT JOIN [sys].[key_constraints] AS SKC
ON skc.parent_object_id = TBL.[object_id]
AND SIC.index_column_id = SKC.unique_index_id
LEFT JOIN [sys].[default_constraints] AS SDC
ON SDC.parent_column_id = AC.column_id
LEFT JOIN [sys].[extended_properties] AS SEP
ON SEP.major_id = TBL.[object_id]
AND SEP.minor_id = AC.column_id
LEFT JOIN [sys].[tables] AS TBL_PRIM
ON SFC.referenced_object_id = TBL_PRIM.[object_id]
LEFT JOIN [sys].[columns] AS COL_PRIM
ON SFC.referenced_object_id = COL_PRIM.[object_id]
AND SFC.referenced_column_id = COL_PRIM.column_id
Fill in the question marks in the where clause, and this will give you the name of your default constraint.
SELECT
SchemaName = SCH.[name]
,TableName = TAB.[name]
,ColumnName = COL.[name]
,DefaultConstraint = DFC.[name]
FROM sys.default_constraints AS DFC
JOIN sys.columns AS COL
ON DFC.parent_object_id = COL.[object_id]
AND DFC.parent_column_id = COL.column_id
JOIN sys.tables AS TAB
ON COL.[object_id] = TAB.[object_id]
JOIN SYS.schemas AS SCH
ON TAB.[schema_id] = SCH.[schema_id]
WHERE SCH.[name] = ?
AND TAB.[name] = ?
AND COL.[name] = ?

TSQL / SQL-SERVER: How to find all tables in a snapshot replication that have primary keys

I've been tasked with moving all tables in a single snapshot replication that have primary keys to the transaction replication. We get vendor updates and they may have added keys to tables that were in the Snapshot replication.
I've tried to break it down into 2 steps, finding all tables in a snapshot replication, and then checking to see if those tables have a primary key.
I've tried to piece together a few different code samples, but I may need to start over, here's what I've got so far.
--=============================================================================================
SELECT DB_NAME () PublisherDB
, sp.name AS PublisherName
, sa.name AS TableName
, UPPER (srv.srvname) AS SubscriberServerName
,*
FROM dbo.syspublications sp
JOIN dbo.sysarticles sa ON sp.pubid = sa.pubid
JOIN dbo.syssubscriptions s ON sa.artid = s.artid
JOIN master.dbo.sysservers srv ON s.srvid = srv.srvid;
--=============================================================================================
SELECT DB_NAME () AS db
, SCHEMA_NAME (o.schema_id) AS [Schema]
, so.name AS table_name
, so.type
, CASE WHEN TABLE_NAME IN (
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY'
) THEN 1 ELSE 0 END AS HasPrimaryKey
--INTO #t2
FROM sys.objects o WITH (NOLOCK)
INNER JOIN sysobjects so WITH (NOLOCK)
--INNER JOIN #t1 ON t1.
LEFT OUTER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS t2 ON t2.TABLE_NAME = so.name ON so.id = o.object_id
WHERE (
(so.xtype = 'U') -- user table xtype: learn.microsoft.com/en-us/sql/relational-databases/system-compatibility-views/sys-sysobjects-transact-sql?view=sql-server-ver15
OR (so.xtype = 'V') -- view
OR (so.xtype = 'P') -- stored procedure
)
AND so.category <> 2
AND so.name IN (
SELECT DISTINCT OBJECT_NAME (objid) FROM dbo.sysarticles
)
ORDER BY so.name
, so.type;
--=============================================================================================
DECLARE #jobId UNIQUEIDENTIFIER;
DECLARE #jobName sysname;
SELECT #jobId = jobs.job_id
, #jobName = jobs.name
FROM msdb.dbo.sysjobs jobs (NOLOCK)
JOIN msdb.dbo.syscategories categories (NOLOCK) ON jobs.category_id = categories.category_id
WHERE categories.name = 'REPL-Snapshot'
AND jobs.name LIKE '%db-name%';
SELECT #jobId
, #jobName;
EXEC sp_start_job #job_id = #jobId;
This is what I ended up going with. I pieced together and tweaked various snippets of code I've found.
Some from here: https://dataedo.com/kb/query/sql-server/list-tables-with-their-primary-keys
Other code from here: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/50c6890b-8dc1-46c6-aeda-d97149a9692f/list-all-replicated-tables-and-their-destination?forum=sqlreplication
--====================================================================================================================================================
-- Get tables in Snapshot replication for the selected DB.
--====================================================================================================================================================
IF OBJECT_ID ('tempdb..#t1') IS NOT NULL DROP TABLE #t1;
SELECT pub.name AS [Publication]
, CASE WHEN pub.name LIKE '%Snapshot%' THEN 'SnapShot'
WHEN pub.name LIKE '%Transaction%' THEN 'Transaction' ELSE NULL END AS ReplicationType
, art.name AS [Article]
, serv.name AS [Subsriber]
, sub.dest_db AS [DestinationDB]
, obj.object_id
, CASE WHEN obj.type = 'U' THEN 'Table'
WHEN obj.type = 'V' THEN 'View'
WHEN obj.type = 'P' THEN 'SP' ELSE NULL END AS ObjectType
INTO #t1
FROM dbo.syssubscriptions sub
INNER JOIN sys.servers serv ON serv.server_id = sub.srvid
INNER JOIN dbo.sysarticles art ON art.artid = sub.artid
INNER JOIN dbo.syspublications pub ON pub.pubid = art.pubid
INNER JOIN sys.objects obj ON obj.object_id = art.objid
WHERE CASE WHEN pub.name LIKE '%Snapshot%' THEN 'SnapShot'
WHEN pub.name LIKE '%Transaction%' THEN 'Transaction' ELSE NULL END = 'Snapshot';
--====================================================================================================================================================
-- Check for primary keys on the above tables
--====================================================================================================================================================
SELECT SCHEMA_NAME (tab.schema_id) AS [schema_name]
, tab.[name] AS table_name
, pk.[name] AS pk_name
, SUBSTRING (column_names, 1, LEN (column_names) - 1) AS [columns]
FROM sys.tables tab
LEFT OUTER JOIN sys.indexes pk ON tab.object_id = pk.object_id
AND pk.is_primary_key = 1
CROSS APPLY (
SELECT col.[name] + ', '
FROM sys.index_columns ic
INNER JOIN sys.columns col ON ic.object_id = col.object_id
AND ic.column_id = col.column_id
WHERE ic.object_id = tab.object_id
AND ic.index_id = pk.index_id
ORDER BY col.column_id
FOR XML PATH ('')
) D(column_names)
WHERE pk.object_id IN (
SELECT object_id FROM #t1
)
ORDER BY SCHEMA_NAME (tab.schema_id)
, tab.[name];

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

Get index statistics information for tables referenced in a specific view

I'm trying to amend the following script to point at just the indexes associated with a particular view vw_foo. Is this possible?
SELECT name AS index_name,
STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated
FROM sys.indexes
Edit
When I say "associated" I mean the indexes on the underlying tables that are used to create the view
Possibly, it will be helpful for you -
SELECT
SCHEMA_NAME(o.[schema_id]) + '.' + o.name
, s.name
, statistics_update_date = STATS_DATE(o.[object_id], stats_id)
FROM sys.objects o
JOIN sys.stats s ON o.[object_id] = s.[object_id]
WHERE o.[type] = 'V' AND o.name = 'vw_foo'
DECLARE #table_name SYSNAME
SELECT #table_name = 'dbo.vw_foo'
EDITED
When I say "associated" I mean the indexes on the tables that are used
by the view
This query returns the list of the views where is used the specified table + shows additional info about the used index -
SELECT
o.table_name
, b.view_name
, i.name
, stast_updates = STATS_DATE(i.[object_id], i.index_id)
, dm_ius.last_user_seek
, dm_ius.last_user_scan
, dm_ius.last_user_lookup
, dm_ius.last_user_update
, dm_ius.user_updates
, dm_ius.user_lookups
, dm_ius.user_scans
, dm_ius.user_seeks
FROM (
SELECT
table_name = s.name + '.' + o.name
, o.[object_id]
FROM sys.objects o
JOIN sys.schemas s ON o.[schema_id] = s.[schema_id]
WHERE o.[type] = 'U'
AND s.name + '.' + o.name = #table_name
) o
JOIN sys.indexes i ON o.[object_id] = i.[object_id]
AND i.[type] > 0
AND i.is_disabled = 0
AND i.is_hypothetical = 0
LEFT JOIN sys.dm_db_index_usage_stats dm_ius ON i.index_id = dm_ius.index_id AND dm_ius.[object_id] = i.[object_id]
OUTER APPLY (
SELECT
view_name = r.referencing_schema_name + '.' + r.referencing_entity_name
, r.referencing_id
FROM sys.dm_sql_referencing_entities (o.table_name, 'OBJECT') r
JOIN sys.objects o2 ON r.referencing_id = o2.[object_id]
WHERE o2.[type] = 'V'
) b
WHERE b.view_name IS NOT NULL
The existing answers were probably heading towards checking the name in sys.objects but never do it. But there's no need to do so anyway, since the OBJECT_ID() function lets you get an object_id in a clean fashion:
SELECT name AS index_name,
STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated
FROM sys.indexes
WHERE object_id = OBJECT_ID('vw_foo')

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