SQL Server Find Index Definitions - sql-server

SQL Server Find Index Definitions
I am tasked to migrate a set of tables schema, content, and table objects to an Azure SQLdb. I ran in to a problem where triggers and indexes. They didn't get copied over. Triggers were easy to get from the sys.modules table but no luck with indexes.

I had no luck finding anything here or on the interwebs so I wrote this. I hope this helps someone.
/*
========================WARNING!!!!!!!!================================
The follow has the following defaults that may not suite your needs.
PRIMARY KEY CLUSTERED
STATISTICS_NORECOMPUTE = OFF
SORT_IN_TEMPDB = OFF I leave this on Since my TempDB has the room,
bandwidth, and it's own IO channel.
It's up to you though.
ONLINE = OFF
Created ON [PRIMARY]
Created by: Frank Canapa
Date 2020-07-24
Based on the work of others on the interwebs
*/
;WITH MyCTE
AS
(
SELECT T = t.[name]
,A = 'ALTER TABLE [' + schema_name(t.schema_id) + '].[' + t.[name]+'] ADD CONSTRAINT [' + i.[name] + '] PRIMARY KEY CLUSTERED (' + substring(column_names, 1, len(column_names)-1)
, B =')WITH (PAD_INDEX = ' +
CASE WHEN i.[is_padded] = 0 THEN 'OFF'
WHEN i.[is_padded] = 1 THEN 'ON'
END
, C =', STATISTICS_NORECOMPUTE = OFF' + ', SORT_IN_TEMPDB = OFF' + ', IGNORE_DUP_KEY = ' +
CASE WHEN i.[IGNORE_DUP_KEY] = 0 THEN 'OFF'
WHEN i.[IGNORE_DUP_KEY] = 1 THEN 'ON'
END
, D = ', ONLINE = OFF' + ', ALLOW_ROW_LOCKS = ' +
CASE WHEN i.[ALLOW_ROW_LOCKS] = 0 THEN 'OFF'
WHEN i.[ALLOW_ROW_LOCKS] = 1 THEN 'ON'
END
, E = ', ALLOW_PAGE_LOCKS = ' +
CASE WHEN i.[ALLOW_PAGE_LOCKS] = 0 THEN 'OFF'
WHEN i.[ALLOW_PAGE_LOCKS] = 1 THEN 'ON'
END
, F = CASE WHEN i.[fill_factor] = 0 THEN ''
WHEN i.[fill_factor] > 0 THEN ', FILLFACTOR = ' + CAST(i.[fill_factor] AS varchar(3))
END
, G = ') ON [PRIMARY]'
FROM sys.objects t
INNER JOIN sys.indexes i
ON t.object_id = i.object_id
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 = t.object_id
AND ic.index_id = i.index_id
ORDER by key_ordinal
for xml path ('') ) D (column_names)
WHERE i.[is_primary_key] = 1
AND t.is_ms_shipped <> 1
AND index_id > 0
UNION
SELECT T = t.[name]
,A = 'CREATE ' +
CASE WHEN i.[type] = 1 THEN 'CLUSTERED'
WHEN i.[type] = 2 THEN 'NONCLUSTERED'
WHEN i.[type] = 3 THEN 'XML'
WHEN i.[type] = 4 THEN 'Spatial '
WHEN i.[type] = 5 THEN 'Clustered columnstore'
WHEN i.[type] = 6 THEN 'Nonclustered columnstore'
WHEN i.[type] = 7 THEN 'Nonclustered hash'
END
, B = ' INDEX [' + i.[name] + '] ON ['+ schema_name(t.schema_id) + '].[' + t.[name]+'] ('+substring(column_names, 1, len(column_names)-1) + ')WITH (PAD_INDEX = ' +
CASE WHEN i.[is_padded] = 0 THEN 'OFF'
WHEN i.[is_padded] = 1 THEN 'ON'
END
, C = ', STATISTICS_NORECOMPUTE = OFF' + ', SORT_IN_TEMPDB = OFF' + ', IGNORE_DUP_KEY = ' +
CASE WHEN i.[IGNORE_DUP_KEY] = 0 THEN 'OFF'
WHEN i.[IGNORE_DUP_KEY] = 1 THEN 'ON'
END
, D = ', ONLINE = OFF' + ', ALLOW_ROW_LOCKS = ' +
CASE WHEN i.[ALLOW_ROW_LOCKS] = 0 THEN 'OFF'
WHEN i.[ALLOW_ROW_LOCKS] = 1 THEN 'ON'
END
, E = ', ALLOW_PAGE_LOCKS = ' +
CASE WHEN i.[ALLOW_PAGE_LOCKS] = 0 THEN 'OFF'
WHEN i.[ALLOW_PAGE_LOCKS] = 1 THEN 'ON'
END
, F = CASE WHEN i.[fill_factor] = 0 THEN ''
WHEN i.[fill_factor] > 0 THEN ', FILLFACTOR = ' + CAST(i.[fill_factor] AS varchar(3))
END
, G = ') ON [PRIMARY]'
FROM sys.objects t
INNER JOIN sys.indexes i
ON t.object_id = i.object_id
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 = t.object_id
AND ic.index_id = i.index_id
ORDER by key_ordinal
for xml path ('') ) D (column_names)
WHERE i.[is_primary_key] = 0
AND substring(i.[name],1,1 ) != '_'
AND t.is_ms_shipped <> 1
AND index_id > 0
)
SELECT T, A + B + C + D + E + F + G
FROM MyCTE
ORDER BY T

Related

SQL Replace All Tables with Clustered Columnstore Index

We are conducting a migration project, and looking to replace most Rowstore indexes with Clustered Columnstore indexes for large Data Warehouse. We are adding a unique index on the identity column.
Does anyone have script to alter run through all 100+ tables, and replace primary key clustered index with Columnstore Index?
Testing to see if columnstore index will help performance tuning if we migrate.
*By the way, are Identity columns recommended in Columnstore? Need way to identify each row (sometimes identity columns may reset, so placing unique constraint, Or should Guids be used?) If not identity, feel free to remove identity column with Guid or something else .
Current:
CREATE TABLE [dbo].[Fact_SalesTransaction]
(
[FactSalesTransactionId] INT IDENTITY (1, 1) NOT NULL,
[DimCustomerId] INT NOT NULL,
[DimSellerId] INT NOT NULL,
[SalesDatetime] DATETIME NULL,
[DimSalesDateId] INT NULL,
[SalesAmount] DECIMAL (28, 2) NULL,
[ETLCreateDate] DATETIME NULL,
CONSTRAINT [pk_SalesTransactionId] PRIMARY KEY CLUSTERED ([SalesTransactionId] ASC)
);
Expected:
CREATE TABLE [dbo].[Fact_SalesTransaction]
(
[FactSalesTransactionId] INT IDENTITY (1, 1) NOT NULL,
[DimCustomerId] INT NOT NULL,
[DimSellerId] INT NOT NULL,
[SalesDatetime] DATETIME NULL,
[DimSalesDateId] INT NULL,
[SalesAmount] DECIMAL (28, 2) NULL,
[ETLCreateDate] DATETIME NULL,
);
CREATE CLUSTERED COLUMNSTORE INDEX ccx_Fact_SalesTransaction ON Fact_SalesTransaction;
CREATE UNIQUE INDEX unx_FactSalesTransactionId ON dbo.Fact_SalesTransaction (FactSalesTransactionId);
We only want to use T-SQL to conduct this on an existing database.
Helpful Resource in Comment: Generate SQL Create Scripts for existing tables with Query
Devart answered this question asking about how to generate a script for a table. I tweaked his code to omit the primary key portion and replaced it with unique key and columnstore creation scripts following his general pattern. I also had to use marc_s's answer to this question about how to find out if a table's primary key is clustered or not. I put all this into a stored procedure called #scriptTable. This is what's below:
create procedure #scriptTable
#table_name sysname,
#sql nvarchar(max) output
as
DECLARE
#object_name SYSNAME
, #object_id INT
SELECT
#object_name = '[' + s.name + '].[' + o.name + ']'
, #object_id = o.[object_id]
FROM sys.objects o WITH (NOWAIT)
JOIN sys.schemas s WITH (NOWAIT) ON o.[schema_id] = s.[schema_id]
WHERE s.name + '.' + o.name = #table_name
AND o.[type] = 'U'
AND o.is_ms_shipped = 0
;WITH index_column AS
(
SELECT
ic.[object_id]
, ic.index_id
, ic.is_descending_key
, ic.is_included_column
, c.name
FROM sys.index_columns ic WITH (NOWAIT)
JOIN sys.columns c WITH (NOWAIT) ON ic.[object_id] = c.[object_id] AND ic.column_id = c.column_id
WHERE ic.[object_id] = #object_id
),
fk_columns AS
(
SELECT
k.constraint_object_id
, cname = c.name
, rcname = rc.name
FROM sys.foreign_key_columns k WITH (NOWAIT)
JOIN sys.columns rc WITH (NOWAIT) ON rc.[object_id] = k.referenced_object_id AND rc.column_id = k.referenced_column_id
JOIN sys.columns c WITH (NOWAIT) ON c.[object_id] = k.parent_object_id AND c.column_id = k.parent_column_id
WHERE k.parent_object_id = #object_id
)
SELECT #sql = 'CREATE TABLE ' + #object_name + CHAR(13) + '(' + CHAR(13) + STUFF((
SELECT CHAR(9) + ', [' + c.name + '] ' +
CASE WHEN c.is_computed = 1
THEN 'AS ' + cc.[definition]
ELSE UPPER(tp.name) +
CASE WHEN tp.name IN ('varchar', 'char', 'varbinary', 'binary', 'text')
THEN '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length AS VARCHAR(5)) END + ')'
WHEN tp.name IN ('nvarchar', 'nchar', 'ntext')
THEN '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length / 2 AS VARCHAR(5)) END + ')'
WHEN tp.name IN ('datetime2', 'time2', 'datetimeoffset')
THEN '(' + CAST(c.scale AS VARCHAR(5)) + ')'
WHEN tp.name = 'decimal'
THEN '(' + CAST(c.[precision] AS VARCHAR(5)) + ',' + CAST(c.scale AS VARCHAR(5)) + ')'
ELSE ''
END +
CASE WHEN c.collation_name IS NOT NULL THEN ' COLLATE ' + c.collation_name ELSE '' END +
CASE WHEN c.is_nullable = 1 THEN ' NULL' ELSE ' NOT NULL' END +
CASE WHEN dc.[definition] IS NOT NULL THEN ' DEFAULT' + dc.[definition] ELSE '' END +
CASE WHEN ic.is_identity = 1 THEN ' IDENTITY(' + CAST(ISNULL(ic.seed_value, '0') AS CHAR(1)) + ',' + CAST(ISNULL(ic.increment_value, '1') AS CHAR(1)) + ')' ELSE '' END
END + CHAR(13)
FROM sys.columns c WITH (NOWAIT)
JOIN sys.types tp WITH (NOWAIT) ON c.user_type_id = tp.user_type_id
LEFT JOIN sys.computed_columns cc WITH (NOWAIT) ON c.[object_id] = cc.[object_id] AND c.column_id = cc.column_id
LEFT JOIN sys.default_constraints dc WITH (NOWAIT) ON c.default_object_id != 0 AND c.[object_id] = dc.parent_object_id AND c.column_id = dc.parent_column_id
LEFT JOIN sys.identity_columns ic WITH (NOWAIT) ON c.is_identity = 1 AND c.[object_id] = ic.[object_id] AND c.column_id = ic.column_id
WHERE c.[object_id] = #object_id
ORDER BY c.column_id
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, CHAR(9) + ' ')
+ ')' + CHAR(13)
+ ISNULL((SELECT (
SELECT CHAR(13) +
'ALTER TABLE ' + #object_name + ' WITH'
+ CASE WHEN fk.is_not_trusted = 1
THEN ' NOCHECK'
ELSE ' CHECK'
END +
' ADD CONSTRAINT [' + fk.name + '] FOREIGN KEY('
+ STUFF((
SELECT ', [' + k.cname + ']'
FROM fk_columns k
WHERE k.constraint_object_id = fk.[object_id]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
+ ')' +
' REFERENCES [' + SCHEMA_NAME(ro.[schema_id]) + '].[' + ro.name + '] ('
+ STUFF((
SELECT ', [' + k.rcname + ']'
FROM fk_columns k
WHERE k.constraint_object_id = fk.[object_id]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
+ ')'
+ CASE
WHEN fk.delete_referential_action = 1 THEN ' ON DELETE CASCADE'
WHEN fk.delete_referential_action = 2 THEN ' ON DELETE SET NULL'
WHEN fk.delete_referential_action = 3 THEN ' ON DELETE SET DEFAULT'
ELSE ''
END
+ CASE
WHEN fk.update_referential_action = 1 THEN ' ON UPDATE CASCADE'
WHEN fk.update_referential_action = 2 THEN ' ON UPDATE SET NULL'
WHEN fk.update_referential_action = 3 THEN ' ON UPDATE SET DEFAULT'
ELSE ''
END
+ CHAR(13) + 'ALTER TABLE ' + #object_name + ' CHECK CONSTRAINT [' + fk.name + ']' + CHAR(13)
FROM sys.foreign_keys fk WITH (NOWAIT)
JOIN sys.objects ro WITH (NOWAIT) ON ro.[object_id] = fk.referenced_object_id
WHERE fk.parent_object_id = #object_id
FOR XML PATH(N''), TYPE).value('.', 'NVARCHAR(MAX)')), '')
+ ISNULL(((SELECT
CHAR(13) + 'CREATE' + CASE WHEN i.is_unique = 1 THEN ' UNIQUE' ELSE '' END
+ ' NONCLUSTERED INDEX [' + i.name + '] ON ' + #object_name + ' (' +
STUFF((
SELECT ', [' + c.name + ']' + CASE WHEN c.is_descending_key = 1 THEN ' DESC' ELSE ' ASC' END
FROM index_column c
WHERE c.is_included_column = 0
AND c.index_id = i.index_id
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '') + ')'
+ ISNULL(CHAR(13) + 'INCLUDE (' +
STUFF((
SELECT ', [' + c.name + ']'
FROM index_column c
WHERE c.is_included_column = 1
AND c.index_id = i.index_id
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '') + ')', '') + CHAR(13)
FROM sys.indexes i WITH (NOWAIT)
WHERE i.[object_id] = #object_id
AND i.is_primary_key = 0
AND i.[type] = 2
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
), '')
+ char(13)
-- Replaced "create primary key" logic in the original with what's below:
+ ISNULL(
(
select 'create clustered columnstore index [ccx_' + #table_name + '] on ' + #object_name + char(13) +
'create unique ' + convert(nvarchar(max), i.type_desc) + ' index [' + replace(k.name, 'pk_', 'unx_') + '] ' +
'on ' + #object_name + ' (' +
(
SELECT STUFF((
SELECT ', [' + ic.name + '] ' + CASE WHEN ic.is_descending_key = 1 THEN 'DESC' ELSE 'ASC' END
FROM index_column ic
WHERE ic.is_included_column = 0
AND ic.[object_id] = k.parent_object_id
AND ic.index_id = k.unique_index_id
FOR XML PATH(N''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
) +
')' + CHAR(13)
FROM sys.key_constraints k WITH (NOWAIT)
join sys.indexes i with (nowait) on k.unique_index_id = i.index_id and k.parent_object_id = i.object_id
WHERE k.parent_object_id = #object_id
AND k.[type] = 'PK'
),
''
);
You can use #scriptTable like this:
declare #sql nvarchar(max);
exec #scriptTable 'dbo.Fact_SalesTransaction', #sql output;
print (#sql);
Replace 'print' with 'exec' or use sp_executeSql when ready.
To use it on all tables, first capture the tables you want to modify:
declare #tables table (
rowId int identity(1,1),
name nvarchar(max)
);
insert #tables
select schema_name(schema_id) + '.' + name
from sys.tables
where type_desc = 'user_table'
Now you're ready to loop the tables and apply #scriptTable:
declare #rowId int = 1;
declare #table nvarchar(max);
declare #sql nvarchar(max);
while #rowId <= (select max(rowId) from #tables) begin
select #table = name from #tables where rowId = #rowId;
exec #scriptTable #table, #sql output;
print (#sql); -- turn 'print' into 'exec' or otherwise use sp_executeSql
set #rowId += 1;
end
As before, replace 'print' with 'exec' or use sp_executeSql when ready.
Note that my portion may need further modification if you have table names that will require brackets around them.
EDIT:
Updated the code a bit to simplify (slightly) and to work with table names needing brackets around them.
For creation of CCI on all tables, you may use the below :
DECLARE #SQLscript nVARCHAR(1000) =
'CREATE CLUSTERED COLUMNSTORE INDEX &&& ON ### WITH (DROP_EXISTING = OFF,COMPRESSION_DELAY = 0)'
declare #tables table (
rowId int identity(1,1),
name nvarchar(max)
);
insert #tables
select schema_name(schema_id) + '.' + name
from sys.tables
where type_desc = 'user_table'
declare #rowId int = 1;
declare #table nvarchar(max);
declare #sql nvarchar(max);
while #rowId <= (select max(rowId) from #tables) begin
select #table = name from #tables where rowId = #rowId;
SET #SQLscript = REPLACE(REPLACE(#SQLscript, '###',#table) ,'&&&','cci_' + SUBSTRING(REPLACE(#table,'].[','_'),CHARINDEX('.',REPLACE(#table,'].[','_'))+1,LEN(REPLACE(#table,'].[','_'))))
BEGIN TRY
EXEC sp_executeSql #SQLscript;
END TRY
BEGIN CATCH
PRINT #SQLscript
END CATCH
SET #SQLscript = 'CREATE CLUSTERED COLUMNSTORE INDEX &&& ON ### WITH (DROP_EXISTING = OFF,COMPRESSION_DELAY = 0)'
set #rowId += 1;
end
The answer of #pwilcox is right, except for the last part where it spits out the code for the rowstore index. That index should not be clustered as the line above already creates the clustered columnstore index.
Fix:
-- Replaced "create primary key" logic in the original with what's below:
+ ISNULL(
(
select 'create clustered columnstore index [ccx_' + #table_name + '] on ' + #object_name + char(13) +
'create unique index [' + replace(k.name, 'pk_', 'unx_') + '] ' +
'on ' + #object_name + ' (' +
(
SELECT STUFF((
SELECT ', [' + ic.name + '] ' + CASE WHEN ic.is_descending_key = 1 THEN 'DESC' ELSE 'ASC' END
FROM index_column ic
WHERE ic.is_included_column = 0
AND ic.[object_id] = k.parent_object_id
AND ic.index_id = k.unique_index_id
FOR XML PATH(N''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
) +
')' + CHAR(13)
FROM sys.key_constraints k WITH (NOWAIT)
join sys.indexes i with (nowait) on k.unique_index_id = i.index_id and k.parent_object_id = i.object_id
WHERE k.parent_object_id = #object_id
AND k.[type] = 'PK'
),
''
);

How to get the STATISTICS_NORECOMPUTE, SORT_IN_TEMPDB, IGNORE_DUP_KEY, DROP_EXISTING, ONLINE options of an index from system table?

I'm trying to build the create index script for the existing indexes of my database. I'm getting information from the sys.objects,sys.indexes and sys.index_columns.
I'm trying to build a script like :
CREATE NONCLUSTERED INDEX [a_Idx] ON [tb_1]
(
[col_1] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
But it seems the options (STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF)
are not in the table sys.indexes.
Could anyone tell me where I could get these information?
Thank you very much
(STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF,
DROP_EXISTING = OFF, ONLINE = OFF)
These are default options..which means..if you create an index with below definition..
create index nci on dbo.tt(id)
all the above options will be included..so you don't need to worry about including them ,unless you wan't to change them..
You also can use this script,if you want to have those options included..
Reference:https://social.technet.microsoft.com/wiki/contents/articles/19598.how-to-generate-index-creation-scripts-for-all-tables-in-a-database-using-t-sql.aspx
SELECT ' CREATE ' +
CASE WHEN I.is_unique = 1 THEN ' UNIQUE ' ELSE '' END +
I.type_desc COLLATE DATABASE_DEFAULT +' INDEX ' +
I.name + ' ON ' +
Schema_name(T.Schema_id)+'.'+T.name + ' ( ' +
KeyColumns + ' ) ' +
ISNULL(' INCLUDE ('+IncludedColumns+' ) ','') +
ISNULL(' WHERE '+I.Filter_definition,'') + ' WITH ( ' +
CASE WHEN I.is_padded = 1 THEN ' PAD_INDEX = ON ' ELSE ' PAD_INDEX = OFF ' END + ',' +
'FILLFACTOR = '+CONVERT(CHAR(5),CASE WHEN I.Fill_factor = 0 THEN 100 ELSE I.Fill_factor END) + ',' +
-- default value
'SORT_IN_TEMPDB = OFF ' + ',' +
CASE WHEN I.ignore_dup_key = 1 THEN ' IGNORE_DUP_KEY = ON ' ELSE ' IGNORE_DUP_KEY = OFF ' END + ',' +
CASE WHEN ST.no_recompute = 0 THEN ' STATISTICS_NORECOMPUTE = OFF ' ELSE ' STATISTICS_NORECOMPUTE = ON ' END + ',' +
-- default value
' DROP_EXISTING = ON ' + ',' +
-- default value
' ONLINE = OFF ' + ',' +
CASE WHEN I.allow_row_locks = 1 THEN ' ALLOW_ROW_LOCKS = ON ' ELSE ' ALLOW_ROW_LOCKS = OFF ' END + ',' +
CASE WHEN I.allow_page_locks = 1 THEN ' ALLOW_PAGE_LOCKS = ON ' ELSE ' ALLOW_PAGE_LOCKS = OFF ' END + ' ) ON [' +
DS.name + ' ] ' [CreateIndexScript]
FROM sys.indexes I
JOIN sys.tables T ON T.Object_id = I.Object_id
JOIN sys.sysindexes SI ON I.Object_id = SI.id AND I.index_id = SI.indid
JOIN (SELECT * FROM (
SELECT IC2.object_id , IC2.index_id ,
STUFF((SELECT ' , ' + C.name + CASE WHEN MAX(CONVERT(INT,IC1.is_descending_key)) = 1 THEN ' DESC ' ELSE ' ASC ' END
FROM sys.index_columns IC1
JOIN Sys.columns C
ON C.object_id = IC1.object_id
AND C.column_id = IC1.column_id
AND IC1.is_included_column = 0
WHERE IC1.object_id = IC2.object_id
AND IC1.index_id = IC2.index_id
GROUP BY IC1.object_id,C.name,index_id
ORDER BY MAX(IC1.key_ordinal)
FOR XML PATH('')), 1, 2, '') KeyColumns
FROM sys.index_columns IC2
--WHERE IC2.Object_id = object_id('Person.Address') --Comment for all tables
GROUP BY IC2.object_id ,IC2.index_id) tmp3 )tmp4
ON I.object_id = tmp4.object_id AND I.Index_id = tmp4.index_id
JOIN sys.stats ST ON ST.object_id = I.object_id AND ST.stats_id = I.index_id
JOIN sys.data_spaces DS ON I.data_space_id=DS.data_space_id
JOIN sys.filegroups FG ON I.data_space_id=FG.data_space_id
LEFT JOIN (SELECT * FROM (
SELECT IC2.object_id , IC2.index_id ,
STUFF((SELECT ' , ' + C.name
FROM sys.index_columns IC1
JOIN Sys.columns C
ON C.object_id = IC1.object_id
AND C.column_id = IC1.column_id
AND IC1.is_included_column = 1
WHERE IC1.object_id = IC2.object_id
AND IC1.index_id = IC2.index_id
GROUP BY IC1.object_id,C.name,index_id
FOR XML PATH('')), 1, 2, '') IncludedColumns
FROM sys.index_columns IC2
--WHERE IC2.Object_id = object_id('Person.Address') --Comment for all tables
GROUP BY IC2.object_id ,IC2.index_id) tmp1
WHERE IncludedColumns IS NOT NULL ) tmp2
ON tmp2.object_id = I.object_id AND tmp2.index_id = I.index_id
WHERE I.is_primary_key = 0 AND I.is_unique_constraint = 0

How can I show the table structure in SQL Server query?

SELECT DateTime, Skill, Name, TimeZone, ID, User, Employee, Leader
FROM t_Agent_Skill_Group_Half_Hour AS t
I need to view the table structure in a query.
For SQL Server, if using a newer version, you can use
select *
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME='tableName'
There are different ways to get the schema. Using ADO.NET, you can use the schema methods. Use the DbConnection's GetSchema method or the DataReader'sGetSchemaTable method.
Provided that you have a reader for the for the query, you can do something like this:
using(DbCommand cmd = ...)
using(var reader = cmd.ExecuteReader())
{
var schema = reader.GetSchemaTable();
foreach(DataRow row in schema.Rows)
{
Debug.WriteLine(row["ColumnName"] + " - " + row["DataTypeName"])
}
}
See this article for further details.
sp_help tablename in sql server
desc tablename in oracle
Try this query:
DECLARE #table_name SYSNAME
SELECT #table_name = 'dbo.test_table'
DECLARE
#object_name SYSNAME
, #object_id INT
SELECT
#object_name = '[' + s.name + '].[' + o.name + ']'
, #object_id = o.[object_id]
FROM sys.objects o WITH (NOWAIT)
JOIN sys.schemas s WITH (NOWAIT) ON o.[schema_id] = s.[schema_id]
WHERE s.name + '.' + o.name = #table_name
AND o.[type] = 'U'
AND o.is_ms_shipped = 0
DECLARE #SQL NVARCHAR(MAX) = ''
;WITH index_column AS
(
SELECT
ic.[object_id]
, ic.index_id
, ic.is_descending_key
, ic.is_included_column
, c.name
FROM sys.index_columns ic WITH (NOWAIT)
JOIN sys.columns c WITH (NOWAIT) ON ic.[object_id] = c.[object_id] AND ic.column_id = c.column_id
WHERE ic.[object_id] = #object_id
)
SELECT #SQL = 'CREATE TABLE ' + #object_name + CHAR(13) + '(' + CHAR(13) + STUFF((
SELECT CHAR(9) + ', [' + c.name + '] ' +
CASE WHEN c.is_computed = 1
THEN 'AS ' + cc.[definition]
ELSE UPPER(tp.name) +
CASE WHEN tp.name IN ('varchar', 'char', 'varbinary', 'binary', 'text')
THEN '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length AS VARCHAR(5)) END + ')'
WHEN tp.name IN ('nvarchar', 'nchar', 'ntext')
THEN '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length / 2 AS VARCHAR(5)) END + ')'
WHEN tp.name IN ('datetime2', 'time2', 'datetimeoffset')
THEN '(' + CAST(c.scale AS VARCHAR(5)) + ')'
WHEN tp.name = 'decimal'
THEN '(' + CAST(c.[precision] AS VARCHAR(5)) + ',' + CAST(c.scale AS VARCHAR(5)) + ')'
ELSE ''
END +
CASE WHEN c.collation_name IS NOT NULL THEN ' COLLATE ' + c.collation_name ELSE '' END +
CASE WHEN c.is_nullable = 1 THEN ' NULL' ELSE ' NOT NULL' END +
CASE WHEN dc.[definition] IS NOT NULL THEN ' DEFAULT' + dc.[definition] ELSE '' END +
CASE WHEN ic.is_identity = 1 THEN ' IDENTITY(' + CAST(ISNULL(ic.seed_value, '0') AS CHAR(1)) + ',' + CAST(ISNULL(ic.increment_value, '1') AS CHAR(1)) + ')' ELSE '' END
END + CHAR(13)
FROM sys.columns c WITH (NOWAIT)
JOIN sys.types tp WITH (NOWAIT) ON c.user_type_id = tp.user_type_id
LEFT JOIN sys.computed_columns cc WITH (NOWAIT) ON c.[object_id] = cc.[object_id] AND c.column_id = cc.column_id
LEFT JOIN sys.default_constraints dc WITH (NOWAIT) ON c.default_object_id != 0 AND c.[object_id] = dc.parent_object_id AND c.column_id = dc.parent_column_id
LEFT JOIN sys.identity_columns ic WITH (NOWAIT) ON c.is_identity = 1 AND c.[object_id] = ic.[object_id] AND c.column_id = ic.column_id
WHERE c.[object_id] = #object_id
ORDER BY c.column_id
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, CHAR(9) + ' ')
+ ISNULL((SELECT CHAR(9) + ', CONSTRAINT [' + k.name + '] PRIMARY KEY (' +
(SELECT STUFF((
SELECT ', [' + c.name + '] ' + CASE WHEN ic.is_descending_key = 1 THEN 'DESC' ELSE 'ASC' END
FROM sys.index_columns ic WITH (NOWAIT)
JOIN sys.columns c WITH (NOWAIT) ON c.[object_id] = ic.[object_id] AND c.column_id = ic.column_id
WHERE ic.is_included_column = 0
AND ic.[object_id] = k.parent_object_id
AND ic.index_id = k.unique_index_id
FOR XML PATH(N''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, ''))
+ ')' + CHAR(13)
FROM sys.key_constraints k WITH (NOWAIT)
WHERE k.parent_object_id = #object_id
AND k.[type] = 'PK'), '') + ')' + CHAR(13)
PRINT #SQL
Output:
CREATE TABLE [dbo].[test_table]
(
[WorkOutID] BIGINT NOT NULL IDENTITY(1,1)
, [DateOut] DATETIME NOT NULL
, [EmployeeID] INT NOT NULL
, [IsMainWorkPlace] BIT NOT NULL DEFAULT((1))
, [WorkPlaceUID] UNIQUEIDENTIFIER NULL
, [WorkShiftCD] NVARCHAR(10) COLLATE Cyrillic_General_CI_AS NULL
, [CategoryID] INT NULL
, CONSTRAINT [PK_WorkOut] PRIMARY KEY ([WorkOutID] ASC)
)
Also read this:
http://www.c-sharpcorner.com/UploadFile/67b45a/how-to-generate-a-create-table-script-for-an-existing-table/
On SQL Server 2012, you can use the following stored procedure:
sp_columns '<table name>'
For example, given a database table named users:
sp_columns 'users'
In SQL Server, you can use this query:
USE Database_name
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='Table_Name';
And do not forget to replace Database_name and Table_name with the exact names of your database and table names.
For recent versions of SQL Server Management Studio Write the in a query editor and Do "Alt" + "F1"
Try this query:
select *
from (SELECT TABLE_SCHEMA
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='brands')[.brands];
To print a schema, I use jade and do an export to a file of the database then bring it into word to format and print
I was trying 'DESC table_name' but then this worked for me in psql:
select *
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME='table_name';
Another way is,
mysql > SHOW CREATE TABLE my_db.my_table;
You should get the table name and create table sql

List all indexes with included columns(nonkeys)

I had tried sp_helpindex but it shows the columns that have index not the included columns. Please tell me how to list all indexes with included columns(nonkeys)?
Try this T-SQL query against the catalog views:
SELECT
IndexName = i.Name,
ColName = c.Name
FROM
sys.indexes i
INNER JOIN
sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
INNER JOIN
sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
WHERE
ic.is_included_column = 1
ORDER BY
i.Name
It basically checks all indexes (sys.indexes) and then links to their columns and checks to see which columns are designed as included columns (ic.is_included_column = 1) and then lists out all those indexes and all those columns.
Copied from http://www.midnightdba.com/Jen/2009/12/get-index-included-column-info/
SELECT
OBJECT_NAME(i.[object_id]) TableName ,
i.[name] IndexName ,
c.[name] ColumnName ,
ic.is_included_column ,
i.index_id ,
i.type_desc ,
i.is_unique ,
i.data_space_id ,
i.ignore_dup_key ,
i.is_primary_key ,
i.is_unique_constraint
FROM
sys.indexes i
JOIN sys.index_columns ic ON ic.object_id = i.object_id and i.index_id = ic.index_id
JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
ORDER BY
tableName ,
ic.index_id ,
ic.index_column_id
If you want a globally system stored procedure available to get index keys/nonkeys(include) columns then run the following code
USE master
GO
CREATE PROCEDURE sp_helpcolindex
#objname NVARCHAR(776)
AS
BEGIN
SELECT
c.Name,
CASE ic.is_included_column WHEN 0 THEN 'Key' ELSE 'Include' END AS [Type]
FROM sys.indexes i
JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
WHERE i.name = #objname
ORDER BY [Type] DESC
END
GO
EXEC sp_ms_marksystemobject 'sp_helpcolindex'
GO
I know this is quite old, but I've created a modified version of sp_helpindex that outputs the include columns.
use master;
if object_id('dbo.sp_helpindex2') is not null
drop procedure dbo.sp_helpindex2;
go
create procedure dbo.sp_helpindex2(
#objname nvarchar(776)-- the table to check for indexes
)
as
begin
-- PRELIM
set nocount on;
declare
#objid int -- the object id of the table
,#indid smallint -- the index id of an index
,#groupid int -- the filegroup id of an index
,#indname sysname
,#groupname sysname
,#status int
,#keys nvarchar(2126) -- Length (16*max_identifierLength)+(15*2)+(16*3)
,#includes nvarchar(2126) -- Length (16*max_identifierLength)+(15*2)+(16*3)
,#dbname sysname
,#ignore_dup_key bit
,#is_unique bit
,#is_hypothetical bit
,#is_primary_key bit
,#is_unique_key bit
,#is_columnstore bit
,#auto_created bit
,#no_recompute bit
,#memory_optimized bit -- For hekaton tables
,#hash_index bit; -- The index is a hash index
-- Check to see that the object names are local to the current database.
select #dbname = parsename(#objname,3);
if #dbname is null
select #dbname = db_name();
else if #dbname <> db_name()
begin
raiserror(15250,-1,-1);
return (1)
end;
-- Check to see that the table exists and initialize #objid.
select #objid = object_id(#objname);
if #objid is null
begin
raiserror(15009,-1,-1,#objname,#dbname);
return (1)
end;
-- OPEN CURSOR OVER INDEXES (skip stats: bug shiloh_51196)
declare ms_crs_ind cursor local static
for select
i.index_id
,i.data_space_id
,i.name
,i.ignore_dup_key
,i.is_unique
,i.is_hypothetical
,i.is_primary_key
,i.is_unique_constraint
,case
when type = 5 or type = 6 then 1
else 0
end
,case
when type = 5 or type = 6 then 0
else s.auto_created
end
,case
when type = 5 or type = 6 then 0
else s.no_recompute
end
,case
when type = 7 then 1
else 0
end
from sys.indexes as i
left join sys.stats as s
on i.object_id = s.object_id
and i.index_id = s.stats_id
where i.object_id = #objid
and type in ( 1,2,5,6,7 );
open ms_crs_ind;
fetch ms_crs_ind into
#indid
,#groupid
,#indname
,#ignore_dup_key
,#is_unique
,#is_hypothetical
,#is_primary_key
,#is_unique_key
,#is_columnstore
,#auto_created
,#no_recompute
,#hash_index;
-- IF NO INDEX, QUIT
if ##fetch_status < 0
begin
deallocate ms_crs_ind;
raiserror(15472,-1,-1,#objname); -- Object does not have any indexes.
return (0)
end;
if (select object_id('tempdb..#spindtab')) is not null
drop table #spindtab
create table #spindtab
(
index_name sysname collate catalog_default not null
,index_id int
,ignore_dup_key bit
,is_unique bit
,is_hypothetical bit
,is_primary_key bit
,is_unique_key bit
,is_columnstore bit
,auto_created bit
,no_recompute bit
,memory_optimized bit
,hash_index bit
,groupname sysname collate catalog_default null
,index_keys nvarchar(2126) collate catalog_default null -- see #keys above for length descr
,include_cols nvarchar(2126) collate catalog_default null -- see #keys above for length descr
);
-- Now check out each index, figure out its type and keys and
-- save the info in a temporary table that we'll print out at the end.
while ##fetch_status >= 0
begin
-- First we'll figure out what the keys are.
declare
#i int
,#thiskey nvarchar(131) -- 128+3
,#is_include_column bit;
select
#keys = ''
,#includes = '';
declare jbo_crs_ind_cols cursor local static
for select
c.name
,ic.is_included_column
from sys.indexes as i
inner join sys.index_columns as ic
on ic.index_id = i.index_id
and ic.object_id = i.object_id
inner join sys.columns as c
on c.column_id = ic.column_id
and c.object_id = ic.object_id
where i.object_id = #objid
and i.index_id = #indid
order by ic.is_included_column, ic.index_column_id;
open jbo_crs_ind_cols;
fetch jbo_crs_ind_cols
into #thiskey, #is_include_column
if ##fetch_status < 0
begin
deallocate jbo_crs_ind_cols;
continue;
end;
while ##fetch_status >= 0
begin
if(#is_include_column = 0)
select #keys = #keys + iif(len(#keys) > 0, ', ', '') + #thiskey
else
select #includes = #includes + iif(len(#includes) > 0, ', ', '') + #thiskey
fetch jbo_crs_ind_cols
into #thiskey, #is_include_column
end
deallocate jbo_crs_ind_cols;
select #groupname = null;
if serverproperty('EngineEdition') != 5
select #groupname = name
from sys.data_spaces
where data_space_id = #groupid;
select #memory_optimized = is_memory_optimized
from sys.tables
where object_id = #objid;
-- INSERT ROW FOR INDEX
insert into #spindtab
values
(
#indname
,#indid
,#ignore_dup_key
,#is_unique
,#is_hypothetical
,#is_primary_key
,#is_unique_key
,#is_columnstore
,#auto_created
,#no_recompute
,#memory_optimized
,#hash_index
,#groupname
,#keys
,#includes
);
-- Next index
fetch ms_crs_ind into
#indid
,#groupid
,#indname
,#ignore_dup_key
,#is_unique
,#is_hypothetical
,#is_primary_key
,#is_unique_key
,#is_columnstore
,#auto_created
,#no_recompute
,#hash_index;
end;
deallocate ms_crs_ind;
-- DISPLAY THE RESULTS
select
'index_name' = index_name
,'index_description' = convert(varchar(210), --bits 16 off, 1, 2, 16777216 on, located on group
case
when index_id = 1 then 'clustered'
else 'nonclustered'
end +
case
when hash_index = 1 then ' hash'
else ''
end +
case
when ignore_dup_key <> 0 then ', ignore duplicate keys'
else ''
end +
case
when is_unique <> 0 then ', unique'
else ''
end +
case
when is_hypothetical <> 0 then ', hypothetical'
else ''
end +
case
when is_primary_key <> 0 then ', primary key'
else ''
end +
case
when is_unique_key <> 0 then ', unique key'
else ''
end +
case
when is_columnstore <> 0 then ', columnstore'
else ''
end +
case
when auto_created <> 0 then ', auto create'
else ''
end +
case
when no_recompute <> 0 then ', stats no recompute'
else ''
end +
case
when memory_optimized = 1 then ' located in MEMORY '
else ''
end +
case
when groupname is not null
and (memory_optimized = 0
or memory_optimized is null) then ' located on ' + groupname
else ''
end)
,'index_keys' = index_keys
,'include_cols' = include_cols
from #spindtab
order by
index_name;
return (0) -- sp_helpindex2
end
execute sp_ms_marksystemobject 'dbo.sp_helpindex2';

Listing all indexes

I'm wondering what the simplest way to list all indexes for all tables in a database is.
Should I call sp_helpindex for each table and store the results in a temp table, or is there an easier way?
Can anyone explain why constraints are stored in sysobjects but indexes are not?
Here's an example of the kind of query you need:
select
i.name as IndexName,
o.name as TableName,
ic.key_ordinal as ColumnOrder,
ic.is_included_column as IsIncluded,
co.[name] as ColumnName
from sys.indexes i
join sys.objects o on i.object_id = o.object_id
join sys.index_columns ic on ic.object_id = i.object_id
and ic.index_id = i.index_id
join sys.columns co on co.object_id = i.object_id
and co.column_id = ic.column_id
where i.[type] = 2
and i.is_unique = 0
and i.is_primary_key = 0
and o.[type] = 'U'
--and ic.is_included_column = 0
order by o.[name], i.[name], ic.is_included_column, ic.key_ordinal
;
This one is somewhat specific to a certain purpose (I use it in a little C# app to find duplicate indexes and format the output so it's actually readable by a human). But you could easily adapt it to your needs.
You could reference sysindexes
Another trick is to look at the text of sp_helpindex to see how it reconstructs information from the underlying tables.
sp_helptext 'sp_helpindex'
I don't have a reference for this, but I believe constraints are not stored in sysobjects because they are a different kind of thing; sysindexes contains meta-data about objects in sysobjects.
If you need more information, here is a nice SQL script, which I use from time to time:
DECLARE #TabName varchar(100)
CREATE TABLE #temp (
TabName varchar(200), IndexName varchar(200), IndexDescr varchar(200),
IndexKeys varchar(200), IndexSize int
)
DECLARE cur CURSOR FAST_FORWARD LOCAL FOR
SELECT name FROM sysobjects WHERE xtype = 'U'
OPEN cur
FETCH NEXT FROM cur INTO #TabName
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO #temp (IndexName, IndexDescr, IndexKeys)
EXEC sp_helpindex #TabName
UPDATE #temp SET TabName = #TabName WHERE TabName IS NULL
FETCH NEXT FROM cur INTO #TabName
END
CLOSE cur
DEALLOCATE cur
DECLARE #ValueCoef int
SELECT #ValueCoef = low FROM Master.dbo.spt_values WHERE number = 1 AND type = N'E'
UPDATE #temp SET IndexSize =
((CAST(sysindexes.used AS bigint) * #ValueCoef)/1024)/1024
FROM sysobjects INNER JOIN sysindexes ON sysobjects.id = sysindexes.id
INNER JOIN #temp T ON T.TabName = sysobjects.name AND T.IndexName = sysindexes.name
SELECT * FROM #temp
ORDER BY TabName, IndexName
DROP TABLE #temp
Here is a script that will return SQL statements to recreate all the indexes in a database.
SELECT ' CREATE ' +
CASE
WHEN I.is_unique = 1 THEN ' UNIQUE '
ELSE ''
END +
I.type_desc COLLATE DATABASE_DEFAULT + ' INDEX ' +
I.name + ' ON ' +
SCHEMA_NAME(T.schema_id) + '.' + T.name + ' ( ' +
KeyColumns + ' ) ' +
ISNULL(' INCLUDE (' + IncludedColumns + ' ) ', '') +
ISNULL(' WHERE ' + I.filter_definition, '') + ' WITH ( ' +
CASE
WHEN I.is_padded = 1 THEN ' PAD_INDEX = ON '
ELSE ' PAD_INDEX = OFF '
END + ',' +
'FILLFACTOR = ' + CONVERT(
CHAR(5),
CASE
WHEN I.fill_factor = 0 THEN 100
ELSE I.fill_factor
END
) + ',' +
-- default value
'SORT_IN_TEMPDB = OFF ' + ',' +
CASE
WHEN I.ignore_dup_key = 1 THEN ' IGNORE_DUP_KEY = ON '
ELSE ' IGNORE_DUP_KEY = OFF '
END + ',' +
CASE
WHEN ST.no_recompute = 0 THEN ' STATISTICS_NORECOMPUTE = OFF '
ELSE ' STATISTICS_NORECOMPUTE = ON '
END + ',' +
' ONLINE = OFF ' + ',' +
CASE
WHEN I.allow_row_locks = 1 THEN ' ALLOW_ROW_LOCKS = ON '
ELSE ' ALLOW_ROW_LOCKS = OFF '
END + ',' +
CASE
WHEN I.allow_page_locks = 1 THEN ' ALLOW_PAGE_LOCKS = ON '
ELSE ' ALLOW_PAGE_LOCKS = OFF '
END + ' ) ON [' +
DS.name + ' ] ' + CHAR(13) + CHAR(10) + ' GO' [CreateIndexScript]
FROM sys.indexes I
JOIN sys.tables T
ON T.object_id = I.object_id
JOIN sys.sysindexes SI
ON I.object_id = SI.id
AND I.index_id = SI.indid
JOIN (
SELECT *
FROM (
SELECT IC2.object_id,
IC2.index_id,
STUFF(
(
SELECT ' , ' + C.name + CASE
WHEN MAX(CONVERT(INT, IC1.is_descending_key))
= 1 THEN
' DESC '
ELSE
' ASC '
END
FROM sys.index_columns IC1
JOIN sys.columns C
ON C.object_id = IC1.object_id
AND C.column_id = IC1.column_id
AND IC1.is_included_column =
0
WHERE IC1.object_id = IC2.object_id
AND IC1.index_id = IC2.index_id
GROUP BY
IC1.object_id,
C.name,
index_id
ORDER BY
MAX(IC1.key_ordinal)
FOR XML PATH('')
),
1,
2,
''
) KeyColumns
FROM sys.index_columns IC2
--WHERE IC2.Object_id = object_id('Person.Address') --Comment for all tables
GROUP BY
IC2.object_id,
IC2.index_id
) tmp3
)tmp4
ON I.object_id = tmp4.object_id
AND I.Index_id = tmp4.index_id
JOIN sys.stats ST
ON ST.object_id = I.object_id
AND ST.stats_id = I.index_id
JOIN sys.data_spaces DS
ON I.data_space_id = DS.data_space_id
JOIN sys.filegroups FG
ON I.data_space_id = FG.data_space_id
LEFT JOIN (
SELECT *
FROM (
SELECT IC2.object_id,
IC2.index_id,
STUFF(
(
SELECT ' , ' + C.name
FROM sys.index_columns IC1
JOIN sys.columns C
ON C.object_id = IC1.object_id
AND C.column_id = IC1.column_id
AND IC1.is_included_column =
1
WHERE IC1.object_id = IC2.object_id
AND IC1.index_id = IC2.index_id
GROUP BY
IC1.object_id,
C.name,
index_id
FOR XML PATH('')
),
1,
2,
''
) IncludedColumns
FROM sys.index_columns IC2
--WHERE IC2.Object_id = object_id('Person.Address') --Comment for all tables
GROUP BY
IC2.object_id,
IC2.index_id
) tmp1
WHERE IncludedColumns IS NOT NULL
) tmp2
ON tmp2.object_id = I.object_id
AND tmp2.index_id = I.index_id
WHERE I.is_primary_key = 0
AND I.is_unique_constraint = 0
--AND T.name NOT LIKE 'mt_%'
--AND I.name NOT LIKE 'mt_%'
--AND I.Object_id = object_id('Person.Address') --Comment for all tables
--AND I.name = 'IX_Address_PostalCode' --comment for all indexes
I do not have a clear explanation why indexes are not stored in sys.objects. But I would like to contribute to find a simple way to list all indexes for all tables and views in a database. The following query retrieves all indexes including their type and also their object id and object type.
use /*Enter here your database*/
go
select A.Object_id,B.name,B.type,B.type_desc, A.index_id,A.type,A.type_desc
from sys.indexes A left join sys.objects B on A.object_id=B.object_id
where B.type = 'U' or B.type='V' /*filtering on U or V to retrieve tables and views only*/
order by B.name ASC /*Optional sorting*/
I've written this code to iterate through all the databases in your server and push it to a table in a database named Maintenance. You should create this database first and then create a table in that database with the following fields:
CREATE TABLE [dbo].[DBCC_Stats](
[ID] [int] IDENTITY(1,1) NOT NULL,
[DatabaseName] [varchar](50) NULL,
[SchemaName] [nvarchar](128) NULL,
[TableName] [sysname] NOT NULL,
[StatName] [nvarchar](128) NULL,
[modification_counter] [bigint] NULL,
[rows] [bigint] NULL,
[rows_sampled] [bigint] NULL,
[% Rows Sampled] [bigint] NULL,
[last_updated] [datetime2](7) NULL,
[DateEntered] [datetime] NULL,
CONSTRAINT [PK_DBCC_Stats] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[DBCC_Stats] ADD CONSTRAINT [DF_DBCC_Stats_DateEntered] DEFAULT (getdate()) FOR [DateEntered]
To use the stored procedure below you'd pass in the server name.
usp_Execute_Stats '[YourServerName]'
`CREATE PROCEDURE usp_Execute_Stats
#ServerName varchar(100)
AS
BEGIN
DECLARE #strSQL varchar(max)
SET #strSQL='USE ?
SELECT ''' + '?' + ''' AS DatabaseName,OBJECT_SCHEMA_NAME(obj.object_id) SchemaName, obj.name TableName,
stat.name StatName, modification_counter,
[rows], rows_sampled, rows_sampled* 100 / [rows] AS [% Rows Sampled],
last_updated
FROM ' + #ServerName + '.' + '?' + '.sys.objects AS obj
INNER JOIN ' + #ServerName + '.' + '?' + '.sys.stats AS stat ON stat.object_id = obj.object_id
CROSS APPLY sys.dm_db_stats_properties(stat.object_id, stat.stats_id) AS sp
WHERE obj.is_ms_shipped = 0
ORDER BY modification_counter DESC'
INSERT INTO Maintenance.dbo.vwDBCC_Stats
EXEC sp_MSforeachdb #strSQL
--Delete older logs
DELETE Maintenance.dbo.DBCC_Stats
--WHERE DatabaseName IN('Master','Model','MSDB','TempDB')
WHERE [DateEntered] < getdate()-14
END`

Resources