SQL Server数据库中所有索引和索引列的列表
如何获得SQL Server 2005+中所有索引和索引列的列表? 我能得到的最接近的是:
select s.name, t.name, i.name, c.name from sys.tables t inner join sys.schemas s on t.schema_id = s.schema_id inner join sys.indexes i on i.object_id = t.object_id inner join sys.index_columns ic on ic.object_id = t.object_id inner join sys.columns c on c.object_id = t.object_id and ic.column_id = c.column_id where i.index_id > 0 and i.type in (1, 2) -- clustered & nonclustered only and i.is_primary_key = 0 -- do not include PK indexes and i.is_unique_constraint = 0 -- do not include UQ and i.is_disabled = 0 and i.is_hypothetical = 0 and ic.key_ordinal > 0 order by ic.key_ordinal
这不完全是我想要的。
我想要的是,列出所有列的所有用户定义的索引( 这意味着没有支持唯一约束和主键的索引 )(按索引定义中的显示顺序排列)以及尽可能多的元数据。
有两个“sys”目录视图可以参考:
select * from sys.indexes
select * from sys.index_columns
这些会给你几乎任何信息,你可能想要索引和他们的列。
编辑:这个查询越来越接近你在找什么:
SELECT TableName = t.name, IndexName = ind.name, IndexId = ind.index_id, ColumnId = ic.index_column_id, ColumnName = col.name, ind.*, ic.*, col.* FROM sys.indexes ind INNER JOIN sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id INNER JOIN sys.tables t ON ind.object_id = t.object_id WHERE ind.is_primary_key = 0 AND ind.is_unique = 0 AND ind.is_unique_constraint = 0 AND t.is_ms_shipped = 0 ORDER BY t.name, ind.name, ind.index_id, ic.index_column_id;
您可以使用sp_helpindex
查看一个表的所有索引。
EXEC sys.sp_helpindex @objname = N'User' -- nvarchar(77)
对于所有索引,可以遍历sys.objects
以获取每个表的所有索引。
以上都不是为我做的工作,但是这样做:
-- KDF9's concise index list for SQL Server 2005+ (see below for 2000) -- includes schemas and primary keys, in easy to read format -- with unique, clustered, and all ascending/descendings in a single column -- Needs simple manual add or delete to change maximum number of key columns -- but is easy to understand and modify, with no UDFs or complex logic -- SELECT schema_name(schema_id) as SchemaName, OBJECT_NAME(si.object_id) as TableName, si.name as IndexName, (CASE is_primary_key WHEN 1 THEN 'PK' ELSE '' END) as PK, (CASE is_unique WHEN 1 THEN '1' ELSE '0' END)+' '+ (CASE si.type WHEN 1 THEN 'C' WHEN 3 THEN 'X' ELSE 'B' END)+' '+ -- B=basic, C=Clustered, X=XML (CASE INDEXKEY_PROPERTY(si.object_id,index_id,1,'IsDescending') WHEN 0 THEN 'A' WHEN 1 THEN 'D' ELSE '' END)+ (CASE INDEXKEY_PROPERTY(si.object_id,index_id,2,'IsDescending') WHEN 0 THEN 'A' WHEN 1 THEN 'D' ELSE '' END)+ (CASE INDEXKEY_PROPERTY(si.object_id,index_id,3,'IsDescending') WHEN 0 THEN 'A' WHEN 1 THEN 'D' ELSE '' END)+ (CASE INDEXKEY_PROPERTY(si.object_id,index_id,4,'IsDescending') WHEN 0 THEN 'A' WHEN 1 THEN 'D' ELSE '' END)+ (CASE INDEXKEY_PROPERTY(si.object_id,index_id,5,'IsDescending') WHEN 0 THEN 'A' WHEN 1 THEN 'D' ELSE '' END)+ (CASE INDEXKEY_PROPERTY(si.object_id,index_id,6,'IsDescending') WHEN 0 THEN 'A' WHEN 1 THEN 'D' ELSE '' END)+ '' as 'Type', INDEX_COL(schema_name(schema_id)+'.'+OBJECT_NAME(si.object_id),index_id,1) as Key1, INDEX_COL(schema_name(schema_id)+'.'+OBJECT_NAME(si.object_id),index_id,2) as Key2, INDEX_COL(schema_name(schema_id)+'.'+OBJECT_NAME(si.object_id),index_id,3) as Key3, INDEX_COL(schema_name(schema_id)+'.'+OBJECT_NAME(si.object_id),index_id,4) as Key4, INDEX_COL(schema_name(schema_id)+'.'+OBJECT_NAME(si.object_id),index_id,5) as Key5, INDEX_COL(schema_name(schema_id)+'.'+OBJECT_NAME(si.object_id),index_id,6) as Key6 FROM sys.indexes as si LEFT JOIN sys.objects as so on so.object_id=si.object_id WHERE index_id>0 -- omit the default heap and OBJECTPROPERTY(si.object_id,'IsMsShipped')=0 -- omit system tables and not (schema_name(schema_id)='dbo' and OBJECT_NAME(si.object_id)='sysdiagrams') -- omit sysdiagrams ORDER BY SchemaName,TableName,IndexName ------------------------------------------------------------------- -- or to generate creation scripts put a simple wrapper around that SELECT SchemaName, TableName, IndexName, (CASE pk WHEN 'PK' THEN 'ALTER '+ 'TABLE '+SchemaName+'.'+TableName+' ADD CONSTRAINT '+IndexName+' PRIMARY KEY'+ (CASE substring(Type,3,1) WHEN 'C' THEN ' CLUSTERED' ELSE '' END) ELSE 'CREATE '+ (CASE substring(Type,1,1) WHEN '1' THEN 'UNIQUE ' ELSE '' END)+ (CASE substring(Type,3,1) WHEN 'C' THEN 'CLUSTERED ' ELSE '' END)+ 'INDEX '+IndexName+' ON '+SchemaName+'.'+TableName END)+ ' ('+ (CASE WHEN Key1 is null THEN '' ELSE Key1+(CASE substring(Type,4+1,1) WHEN 'D' THEN ' DESC' ELSE '' END) END)+ (CASE WHEN Key2 is null THEN '' ELSE ', '+Key2+(CASE substring(Type,4+2,1) WHEN 'D' THEN ' DESC' ELSE '' END) END)+ (CASE WHEN Key3 is null THEN '' ELSE ', '+Key3+(CASE substring(Type,4+3,1) WHEN 'D' THEN ' DESC' ELSE '' END) END)+ (CASE WHEN Key4 is null THEN '' ELSE ', '+Key4+(CASE substring(Type,4+4,1) WHEN 'D' THEN ' DESC' ELSE '' END) END)+ (CASE WHEN Key5 is null THEN '' ELSE ', '+Key5+(CASE substring(Type,4+5,1) WHEN 'D' THEN ' DESC' ELSE '' END) END)+ (CASE WHEN Key6 is null THEN '' ELSE ', '+Key6+(CASE substring(Type,4+6,1) WHEN 'D' THEN ' DESC' ELSE '' END) END)+ ')' as CreateIndex FROM ( ... ...listing SQL same as above minus the ORDER BY... ... ) as indexes ORDER BY SchemaName,TableName,IndexName ---------------------------------------------------------- -- For SQL Server 2000 the following should work -- change table names to sysindexes and sysobjects (no dots) -- change object_id => id, index_id => indid, -- change is_primary_key => (select count(constid) from sysconstraints as sc where sc.id=si.id and sc.status&15=1) -- change is_unique => INDEXPROPERTY(si.id,si.name,'IsUnique') -- change si.type => INDEXPROPERTY(si.id,si.name,'IsClustered') -- remove all references to schemas including schema name qualifiers, and the XML type -- add select where indid<255 and si.status&64=0 (to omit the text/image index and autostats)
如果您的名字包含空格,请在创build脚本中添加方括号。
当最后一个密钥列全部为空时,您知道没有任何丢失。
过滤出原始请求中的主键等是微不足道的。
注意:请小心使用此解决scheme,因为它不区分索引列和包含列。
– 短而甜:
SELECT OBJECT_SCHEMA_NAME(T.[object_id],DB_ID()) AS [Schema], T.[name] AS [table_name], I.[name] AS [index_name], AC.[name] AS [column_name], I.[type_desc], I.[is_unique], I.[data_space_id], I.[ignore_dup_key], I.[is_primary_key], I.[is_unique_constraint], I.[fill_factor], I.[is_padded], I.[is_disabled], I.[is_hypothetical], I.[allow_row_locks], I.[allow_page_locks], IC.[is_descending_key], IC.[is_included_column] FROM sys.[tables] AS T INNER JOIN sys.[indexes] I ON T.[object_id] = I.[object_id] INNER JOIN sys.[index_columns] IC ON I.[object_id] = IC.[object_id] INNER JOIN sys.[all_columns] AC ON T.[object_id] = AC.[object_id] AND IC.[column_id] = AC.[column_id] WHERE T.[is_ms_shipped] = 0 AND I.[type_desc] <> 'HEAP' ORDER BY T.[name], I.[index_id], IC.[key_ordinal]
以下给出了与sp_helpindex 表名相似的内容
select T.name as TableName, I.name as IndexName, AC.Name as ColumnName, I.type_desc as IndexType from sys.tables as T inner join sys.indexes as I on T.[object_id] = I.[object_id] inner join sys.index_columns as IC on IC.[object_id] = I.[object_id] and IC.[index_id] = I.[index_id] inner join sys.all_columns as AC on IC.[object_id] = AC.[object_id] and IC.[column_id] = AC.[column_id] order by T.name, I.name
嘿家伙,我没有经过,但我得到了原来的作者发布的查询中想要的。
我用它(没有条件/filter)为我的要求,但它给了不正确的结果
主要的问题是在index_id上得到了没有连接条件的交叉积
SELECT S.NAME SCHEMA_NAME,T.NAME TABLE_NAME,I.NAME INDEX_NAME,C.NAME COLUMN_NAME FROM SYS.TABLES T INNER JOIN SYS.SCHEMAS S ON T.SCHEMA_ID = S.SCHEMA_ID INNER JOIN SYS.INDEXES I ON I.OBJECT_ID = T.OBJECT_ID INNER JOIN SYS.INDEX_COLUMNS IC ON IC.OBJECT_ID = T.OBJECT_ID INNER JOIN SYS.COLUMNS C ON C.OBJECT_ID = T.OBJECT_ID **AND IC.INDEX_ID = I.INDEX_ID** AND IC.COLUMN_ID = C.COLUMN_ID WHERE 1=1 ORDER BY I.NAME,I.INDEX_ID,IC.KEY_ORDINAL
这将工作:
DECLARE @IndexInfo TABLE (index_name varchar(250) ,index_description varchar(250) ,index_keys varchar(250) ) INSERT INTO @IndexInfo exec sp_msforeachtable 'sp_helpindex ''?''' select * from @IndexInfo
这不会导致表名,你会得到没有索引的所有表的警告,如果这是一个问题,你可以在这样的索引表上创build一个循环:
DECLARE @IndexInfoTemp TABLE (index_name varchar(250) ,index_description varchar(250) ,index_keys varchar(250) ) DECLARE @IndexInfo TABLE (table_name sysname ,index_name varchar(250) ,index_description varchar(250) ,index_keys varchar(250) ) DECLARE @Tables Table (RowID int not null identity(1,1) ,TableName sysname ) DECLARE @MaxRow int DECLARE @CurrentRow int DECLARE @CurrentTable sysname INSERT INTO @Tables SELECT DISTINCT t.name FROM sys.indexes i INNER JOIN sys.tables t ON i.object_id = t.object_id WHERE i.Name IS NOT NULL SELECT @MaxRow=@@ROWCOUNT,@CurrentRow=1 WHILE @CurrentRow<=@MaxRow BEGIN SELECT @CurrentTable=TableName FROM @Tables WHERE RowID=@CurrentRow INSERT INTO @IndexInfoTemp exec sp_helpindex @CurrentTable INSERT INTO @IndexInfo (table_name , index_name , index_description , index_keys) SELECT @CurrentTable , index_name , index_description , index_keys FROM @IndexInfoTemp DELETE FROM @IndexInfoTemp SET @CurrentRow=@CurrentRow+1 END --WHILE SELECT * from @IndexInfo
编辑
如果你愿意,你可以过滤数据,这里有一些例子(这些工作适用于任何一种方法):
SELECT * FROM @IndexInfo WHERE index_description NOT LIKE '%primary key%' SELECT * FROM @IndexInfo WHERE index_description NOT LIKE '%nonclustered%' AND index_description LIKE '%clustered%' SELECT * FROM @IndexInfo WHERE index_description LIKE '%unique%'
with connect(schema_name,table_name,index_name,index_column_id,column_name) as ( select s.name schema_name, t.name table_name, i.name index_name, index_column_id, cast(c.name as varchar(max)) column_name from sys.tables t inner join sys.schemas s on t.schema_id = s.schema_id inner join sys.indexes i on i.object_id = t.object_id inner join sys.index_columns ic on ic.object_id = t.object_id and ic.index_id=i.index_id inner join sys.columns c on c.object_id = t.object_id and ic.column_id = c.column_id where index_column_id=1 union all select s.name schema_name, t.name table_name, i.name index_name, ic.index_column_id, cast(connect.column_name + ',' + c.name as varchar(max)) column_name from sys.tables t inner join sys.schemas s on t.schema_id = s.schema_id inner join sys.indexes i on i.object_id = t.object_id inner join sys.index_columns ic on ic.object_id = t.object_id and ic.index_id=i.index_id inner join sys.columns c on c.object_id = t.object_id and ic.column_id = c.column_id join connect on connect.index_column_id+1 = ic.index_column_id and connect.schema_name = s.name and connect.table_name = t.name and connect.index_name = i.name) select connect.schema_name,connect.table_name,connect.index_name,connect.column_name from connect join (select schema_name,table_name,index_name,MAX(index_column_id) index_column_id from connect group by schema_name,table_name,index_name) mx on connect.schema_name = mx.schema_name and connect.table_name = mx.table_name and connect.index_name = mx.index_name and connect.index_column_id = mx.index_column_id order by 1,2,3
我需要获得特定的索引,索引列和包含的列。 这是我用过的查询:
SELECT INX.[name] AS [Index Name] ,TBL.[name] AS [Table Name] ,DS1.[IndexColumnsNames] ,DS2.[IncludedColumnsNames] FROM [sys].[indexes] INX INNER JOIN [sys].[tables] TBL ON INX.[object_id] = TBL.[object_id] CROSS APPLY ( SELECT STUFF ( ( SELECT ' [' + CLS.[name] + ']' FROM [sys].[index_columns] INXCLS INNER JOIN [sys].[columns] CLS ON INXCLS.[object_id] = CLS.[object_id] AND INXCLS.[column_id] = CLS.[column_id] WHERE INX.[object_id] = INXCLS.[object_id] AND INX.[index_id] = INXCLS.[index_id] AND INXCLS.[is_included_column] = 0 FOR XML PATH('') ) ,1 ,1 ,'' ) ) DS1 ([IndexColumnsNames]) CROSS APPLY ( SELECT STUFF ( ( SELECT ' [' + CLS.[name] + ']' FROM [sys].[index_columns] INXCLS INNER JOIN [sys].[columns] CLS ON INXCLS.[object_id] = CLS.[object_id] AND INXCLS.[column_id] = CLS.[column_id] WHERE INX.[object_id] = INXCLS.[object_id] AND INX.[index_id] = INXCLS.[index_id] AND INXCLS.[is_included_column] = 1 FOR XML PATH('') ) ,1 ,1 ,'' ) ) DS2 ([IncludedColumnsNames])
这是一种支持索引的方式。 您可以使用SHOWCONTIG来评估碎片。 它将列出数据库或表的所有索引以及统计信息。 我会警告,在一个大型的数据库,它可以是长期运行。 对我来说,这种方法的好处之一是,你不必是一个pipe理员使用它。
– 显示数据库中所有索引的碎片信息
SET NOCOUNT ON USE pubs DBCC SHOWCONTIG WITH ALL_INDEXES GO
…完成后closuresNOCOUNT
– 显示表上所有索引的碎片信息
SET NOCOUNT ON USE pubs DBCC SHOWCONTIG (authors) WITH ALL_INDEXES GO
– 显示特定索引的碎片信息
SET NOCOUNT ON USE pubs DBCC SHOWCONTIG (authors,aunmind) GO
以下工作在SQL Server 2014/2016以及任何Microsoft Azure SQL数据库。
产生一个综合的结果集,可以轻松导出到记事本/ Excel的切片和切割,包括
- 表名
- 索引名称
- 索引说明
- 索引列 – 按顺序
- 包括列 – 为了
SELECT '[' + s.NAME + '].[' + o.NAME + ']' AS 'table_name' ,+ i.NAME AS 'index_name' ,LOWER(i.type_desc) + CASE WHEN i.is_unique = 1 THEN ', unique' ELSE '' END + CASE WHEN i.is_primary_key = 1 THEN ', primary key' ELSE '' END AS 'index_description' ,STUFF(( SELECT ', [' + sc.NAME + ']' AS "text()" FROM syscolumns AS sc INNER JOIN sys.index_columns AS ic ON ic.object_id = sc.id AND ic.column_id = sc.colid WHERE sc.id = so.object_id AND ic.index_id = i1.indid AND ic.is_included_column = 0 ORDER BY key_ordinal FOR XML PATH('') ), 1, 2, '') AS 'indexed_columns' ,STUFF(( SELECT ', [' + sc.NAME + ']' AS "text()" FROM syscolumns AS sc INNER JOIN sys.index_columns AS ic ON ic.object_id = sc.id AND ic.column_id = sc.colid WHERE sc.id = so.object_id AND ic.index_id = i1.indid AND ic.is_included_column = 1 FOR XML PATH('') ), 1, 2, '') AS 'included_columns' FROM sysindexes AS i1 INNER JOIN sys.indexes AS i ON i.object_id = i1.id AND i.index_id = i1.indid INNER JOIN sysobjects AS o ON o.id = i1.id INNER JOIN sys.objects AS so ON so.object_id = o.id AND is_ms_shipped = 0 INNER JOIN sys.schemas AS s ON s.schema_id = so.schema_id WHERE so.type = 'U' AND i1.indid < 255 AND i1.STATUS & 64 = 0 --index with duplicates AND i1.STATUS & 8388608 = 0 --auto created index AND i1.STATUS & 16777216 = 0 --stats no recompute AND i.type_desc <> 'heap' AND so.NAME <> 'sysdiagrams' ORDER BY table_name ,index_name;
我想出了这个,这是给我的确切的概述,我需要。 什么是帮助是你得到索引列聚合到每索引一行。
select o.name as ObjectName, i.name as IndexName, i.is_primary_key as [PrimaryKey], SUBSTRING(i.[type_desc],0,6) as IndexType, i.is_unique as [Unique], Columns.[Normal] as IndexColumns, Columns.[Included] as IncludedColumns from sys.indexes i join sys.objects o on i.object_id = o.object_id cross apply ( select substring ( ( select ', ' + co.[name] from sys.index_columns ic join sys.columns co on co.object_id = i.object_id and co.column_id = ic.column_id where ic.object_id = i.object_id and ic.index_id = i.index_id and ic.is_included_column = 0 order by ic.key_ordinal for xml path('') ) , 3 , 10000 ) as [Normal] , substring ( ( select ', ' + co.[name] from sys.index_columns ic join sys.columns co on co.object_id = i.object_id and co.column_id = ic.column_id where ic.object_id = i.object_id and ic.index_id = i.index_id and ic.is_included_column = 1 order by ic.key_ordinal for xml path('') ) , 3 , 10000 ) as [Included] ) Columns where o.[type] = 'U' --USER_TABLE order by o.[name], i.[name], i.is_primary_key desc
我可能会冒这个饱和问题的另一个答案吗?
这是@marc_s答案的自由重做,与@Tim Ford的一些东西混合在一起,目标是让我的结果更清晰,更简单,最后显示和sorting,以满足我目前的需要。
SELECT OBJECT_SCHEMA_NAME(t.[object_id],DB_ID()) AS [Schema], t.[name] AS [TableName], ind.[name] AS [IndexName], col.[name] AS [ColumnName], ic.column_id AS [ColumnId], ind.[type_desc] AS [IndexTypeDesc], col.is_identity AS [IsIdentity], ind.[is_unique] AS [IsUnique], ind.[is_primary_key] AS [IsPrimaryKey], ic.[is_descending_key] AS [IsDescendingKey], ic.[is_included_column] AS [IsIncludedColumn] FROM sys.indexes ind INNER JOIN sys.index_columns ic ON ind.object_id = ic.object_id AND ind.index_id = ic.index_id INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id INNER JOIN sys.tables t ON ind.object_id = t.object_id WHERE t.is_ms_shipped = 0 --ind.is_primary_key = 1 -- include or not pks, etc --AND ind.is_unique = 0 --AND ind.is_unique_constraint = 0 ORDER BY [Schema], TableName, IndexName, [ColumnId], ColumnName
由于您的configuration文件声明,您正在使用.NET,您可以使用服务器pipe理对象(SMO)编程…否则任何上述答案是太棒了。
上面的解决scheme是优雅的,但根据MS,INDEXKEY_PROPERTY已被弃用。 请参阅: http : //msdn.microsoft.com/en-us/library/ms186773.aspx
基于Tim Ford的代码,这是正确的答案:
select tab.[name] as [table_name], idx.[name] as [index_name], allc.[name] as [column_name], idx.[type_desc], idx.[is_unique], idx.[data_space_id], idx.[ignore_dup_key], idx.[is_primary_key], idx.[is_unique_constraint], idx.[fill_factor], idx.[is_padded], idx.[is_disabled], idx.[is_hypothetical], idx.[allow_row_locks], idx.[allow_page_locks], idxc.[is_descending_key], idxc.[is_included_column], idxc.[index_column_id] from sys.[tables] as tab inner join sys.[indexes] idx on tab.[object_id] = idx.[object_id] inner join sys.[index_columns] idxc on idx.[object_id] = idxc.[object_id] and idx.[index_id] = idxc.[index_id] inner join sys.[all_columns] allc on tab.[object_id] = allc.[object_id] and idxc.[column_id] = allc.[column_id] where tab.[name] Like '%table_name%' and idx.[name] Like '%index_name%' order by tab.[name], idx.[index_id], idxc.[index_column_id]
在Oracle中
select CONNECYBY.SCHEMA_NAME,CONNECYBY.TABLE_NAME,CONNECYBY.INDEX_NAME,CONNECYBY.COLUMN_NAME from ( select TABLE_OWNER SCHEMA_NAME,TABLE_NAME,INDEX_NAME,COLUMN_POSITION,trim(',' from sys_connect_by_path(COLUMN_NAME,',')) COLUMN_NAME from DBA_IND_COLUMNS start with COLUMN_POSITION = 1 connect by TABLE_OWNER = prior TABLE_OWNER and TABLE_NAME = prior TABLE_NAME and INDEX_NAME = prior INDEX_NAME and COLUMN_POSITION = prior COLUMN_POSITION + 1) CONNECYBY join ( select TABLE_OWNER SCHEMA_NAME,TABLE_NAME,INDEX_NAME,max(COLUMN_POSITION) COLUMN_POSITION from DBA_IND_COLUMNS group by TABLE_OWNER,TABLE_NAME,INDEX_NAME) MAX_CONNECYBY on ( CONNECYBY.SCHEMA_NAME = MAX_CONNECYBY.SCHEMA_NAME and CONNECYBY.TABLE_NAME = MAX_CONNECYBY.TABLE_NAME and CONNECYBY.INDEX_NAME = MAX_CONNECYBY.INDEX_NAME and CONNECYBY.COLUMN_POSITION = MAX_CONNECYBY.COLUMN_POSITION) order by CONNECYBY.SCHEMA_NAME,CONNECYBY.TABLE_NAME,CONNECYBY.INDEX_NAME
在SQL Server中
CONNECTBY(SCHEMA_NAME,TABLE_NAME,INDEX_NAME,INDEX_COLUMN_ID,COLUMN_NAME) as ( select SCHEMAS.NAME SCHEMA_NAME , TABLES.NAME TABLE_NAME , INDEXES.NAME INDEX_NAME , INDEX_COLUMNS.INDEX_COLUMN_ID INDEX_COLUMN_ID , cast(COLUMNS.NAME AS VARCHAR(MAX)) COLUMN_NAME from SYS.INDEXES join SYS.TABLES on (INDEXES.OBJECT_ID = TABLES.OBJECT_ID) join SYS.SCHEMAS on (TABLES.SCHEMA_ID = SCHEMAS.SCHEMA_ID) join SYS.INDEX_COLUMNS on ( INDEXES.OBJECT_ID = INDEX_COLUMNS.OBJECT_ID and INDEX_COLUMNS.INDEX_ID = INDEXES.INDEX_ID) join SYS.COLUMNS on ( INDEXES.OBJECT_ID = COLUMNS.OBJECT_ID and INDEX_COLUMNS.COLUMN_ID = COLUMNS.COLUMN_ID) where INDEX_COLUMNS.INDEX_COLUMN_ID = 1 union all select SCHEMAS.NAME SCHEMA_NAME , TABLES.NAME TABLE_NAME , INDEXES.NAME INDEX_NAME , INDEX_COLUMNS.INDEX_COLUMN_ID INDEX_COLUMN_ID , cast(PRIOR.COLUMN_NAME + ',' + COLUMNS.NAME AS VARCHAR(MAX)) COLUMN_NAME from SYS.INDEXES join SYS.TABLES on (INDEXES.OBJECT_ID = TABLES.OBJECT_ID) join SYS.SCHEMAS on (TABLES.SCHEMA_ID = SCHEMAS.SCHEMA_ID) join SYS.INDEX_COLUMNS on ( INDEXES.OBJECT_ID = INDEX_COLUMNS.OBJECT_ID and INDEX_COLUMNS.INDEX_ID = INDEXES.INDEX_ID) join SYS.COLUMNS on ( INDEXES.OBJECT_ID = COLUMNS.OBJECT_ID and INDEX_COLUMNS.COLUMN_ID = COLUMNS.COLUMN_ID) join CONNECTBY as PRIOR on (SCHEMAS.NAME = PRIOR.SCHEMA_NAME and TABLES.NAME = PRIOR.TABLE_NAME and INDEXES.NAME = PRIOR.INDEX_NAME and INDEX_COLUMNS.INDEX_COLUMN_ID = PRIOR.INDEX_COLUMN_ID + 1)) select CONNECTBY.SCHEMA_NAME,CONNECTBY.TABLE_NAME,CONNECTBY.INDEX_NAME,CONNECTBY.COLUMN_NAME from CONNECTBY join ( select SCHEMA_NAME , TABLE_NAME , INDEX_NAME , MAX(INDEX_COLUMN_ID) INDEX_COLUMN_ID from CONNECTBY group by SCHEMA_NAME,TABLE_NAME,INDEX_NAME) MAX_CONNECTBY on (CONNECTBY.SCHEMA_NAME = MAX_CONNECTBY.SCHEMA_NAME and CONNECTBY.TABLE_NAME = MAX_CONNECTBY.TABLE_NAME and CONNECTBY.INDEX_NAME = MAX_CONNECTBY.INDEX_NAME and CONNECTBY.INDEX_COLUMN_ID = MAX_CONNECTBY.INDEX_COLUMN_ID) order by CONNECTBY.SCHEMA_NAME,CONNECTBY.TABLE_NAME,CONNECTBY.INDEX_NAME
请注意,如果要使用上述任何查询来编写索引脚本,则需要在查询中将sys.indexes表中的filter_definition列合并到SQL 2008+中,以获取非聚集索引的filter定义
上午
这是做到这一点的最好方法:
SELECT sys.tables.object_id, sys.tables.name as table_name, sys.columns.name as column_name, sys.indexes.name as index_name, sys.indexes.is_unique, sys.indexes.is_primary_key FROM sys.tables, sys.indexes, sys.index_columns, sys.columns WHERE (sys.tables.object_id = sys.indexes.object_id AND sys.tables.object_id = sys.index_columns.object_id AND sys.tables.object_id = sys.columns.object_id AND sys.indexes.index_id = sys.index_columns.index_id AND sys.index_columns.column_id = sys.columns.column_id) AND sys.tables.name = 'your_table_name'
我更喜欢使用隐式联接,因为它更容易理解。 您可以删除object_id引用,因为您可能不需要它。
干杯。
首先,请注意,上述所有查询都可能错过或错误地包含了指数的INCLUDE列。 另外还有一些是列的正确sorting和/或ASC / DESC选项。
由jona修改了上面的查询。 顺便说一下,在我使用的许多数据库中,我安装了自己的CLR CONCATENATE聚集函数,所以下面的代码依赖于类似的东西。 上面的SQL语句减less到一个更可维护的:
SELECT s.[name] AS [schema_name] , t.[name] AS [table_name] , i.[name] AS [index_name] , dbo.Concatenate(CASE WHEN ic.[key_ordinal] > 0 AND ic.[is_descending_key] = 1 THEN c.[name] + ' DESC' WHEN key_ordinal > 0 THEN c.[name] ELSE NULL END,',',1) AS [columns] , dbo.Concatenate(CASE WHEN ic.[is_included_column] = 1 THEN c.[name] ELSE NULL END,',',1) AS [includes] FROM sys.tables t INNER JOIN sys.schemas s ON t.[schema_id] = s.[schema_id] INNER JOIN sys.indexes i ON i.[object_id] = t.[object_id] INNER JOIN sys.index_columns ic ON ic.[object_id] = t.[object_id] AND ic.index_id = i.index_id INNER JOIN sys.columns c ON c.[object_id] = t.[object_id] AND ic.column_id = c.column_id GROUP BY s.[name] , t.[name] , i.[name] ORDER BY s.[name] , t.[name] , i.[name]
如果您的环境允许添加基于CLR的function,那么在那里有很多连接集合 。
对于每个索引的唯一列:
select s.name, t.name, i.name, i.index_id,c.name,c.column_id from sys.schemas s inner join sys.tables t on t.schema_id = s.schema_id inner join sys.indexes i on i.object_id = t.object_id inner join sys.index_columns ic on ic.object_id = t.object_id and ic.index_id=i.index_id inner join sys.columns c on c.object_id = t.object_id and ic.column_id = c.column_id where i.object_id = object_id('previous.account_1') order by index_id,column_id
下面的查询包含用户定义索引的所有相关信息(对于唯一约束和主键,没有索引),包含所有列:
SELECT I.name as IndexName, CASE WHEN I.is_unique = 1 THEN 'Yes' ELSE 'No' END as 'Unique', I.type_desc COLLATE DATABASE_DEFAULT as Index_Type, '[' + SCHEMA_NAME(T.schema_id) + ']' as 'Schema', '[' + T.name + ']' as TableName, STUFF((SELECT ', [' + C.name + CASE WHEN IC.is_descending_key = 0 THEN '] ASC' ELSE '] DESC' END FROM sys.index_columns IC INNER JOIN sys.columns C ON IC.object_id = C.object_id AND IC.column_id = C.column_id WHERE IC.is_included_column = 0 AND IC.object_id = I.object_id AND IC.index_id = I.Index_id FOR XML PATH('')), 1, 2, '') as Key_Columns, Included_Columns, I.filter_definition, CASE WHEN I.is_padded = 1 THEN 'ON' ELSE 'OFF' END as PAD_INDEX, CASE WHEN ST.no_recompute = 0 THEN 'OFF' ELSE 'ON' END as [Statistics_Norecompute], CONVERT(VARCHAR(5), CASE WHEN I.fill_factor = 0 THEN 100 ELSE I.fill_factor END) as [Fillfactor], CASE WHEN I.ignore_dup_key = 1 THEN 'ON' ELSE 'OFF' END as [Ignore_Dup_Key], CASE WHEN I.allow_row_locks = 1 THEN 'ON' ELSE 'OFF' END as [Allow_Row_Locks], CASE WHEN I.allow_page_locks = 1 THEN 'ON' ELSE 'OFF' END [Allow_Page_Locks] FROM sys.indexes I INNER JOIN sys.tables T ON T.object_id = I.object_id INNER JOIN sys.stats ST ON ST.object_id = I.object_id AND ST.stats_id = I.index_id INNER JOIN sys.data_spaces DS ON I.data_space_id = DS.data_space_id INNER JOIN sys.filegroups FG ON I.data_space_id = FG.data_space_id LEFT OUTER JOIN (SELECT * FROM (SELECT IC2.object_id, IC2.index_id, STUFF((SELECT ', ' + C.name FROM sys.index_columns IC1 INNER 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, '') as Included_Columns FROM sys.index_columns IC2 GROUP BY IC2.object_id, IC2.index_id) tmp1 WHERE Included_Columns 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;
作为额外的好处,下面的查询被格式化为写出创build索引和删除索引脚本:
SELECT I.name as IndexName, -- Uncommnent line below to include checking for index exists as part of the script --'IF NOT EXISTS (SELECT name FROM sysindexes WHERE name = '''+ I.name +''') ' + '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 + '] (' + STUFF( (SELECT ', [' + C.name + CASE WHEN IC.is_descending_key = 0 THEN '] ASC' ELSE '] DESC' END FROM sys.index_columns IC INNER JOIN sys.columns C ON IC.object_id = C.object_id AND IC.column_id = C.column_id WHERE IC.is_included_column = 0 AND IC.object_id = I.object_id AND IC.index_id = I.Index_id FOR XML PATH('')), 1, 2, '') + ') ' + ISNULL(' INCLUDE (' + IncludedColumns + ') ', '') + ISNULL(' WHERE ' + I.filter_definition, '') + 'WITH (PAD_INDEX = ' + CASE WHEN I.is_padded = 1 THEN 'ON' ELSE 'OFF' END + ', STATISTICS_NORECOMPUTE = ' + CASE WHEN ST.no_recompute = 0 THEN 'OFF' ELSE 'ON' END + ', SORT_IN_TEMPDB = OFF' + ', FILLFACTOR = ' + CONVERT(VARCHAR(5), CASE WHEN I.fill_factor = 0 THEN 100 ELSE I.fill_factor END) + ', IGNORE_DUP_KEY = ' + CASE WHEN I.ignore_dup_key = 1 THEN 'ON' ELSE 'OFF' END + ', ONLINE = OFF' + ', ALLOW_ROW_LOCKS = ' + CASE WHEN I.allow_row_locks = 1 THEN 'ON' ELSE 'OFF' END + ', ALLOW_PAGE_LOCKS = ' + CASE WHEN I.allow_page_locks = 1 THEN 'ON' ELSE 'OFF' END + ') ON [' + DS.name + '];' + CHAR(13) + CHAR(10) + 'GO' as [CreateIndex], 'DROP INDEX ['+ I.name +'] ON ['+ SCHEMA_NAME(T.schema_id) +'].['+ T.name +'];' + CHAR(13) + CHAR(10) + 'GO' AS [DropIndex] FROM sys.indexes I INNER JOIN sys.tables T ON T.object_id = I.object_id INNER JOIN sys.stats ST ON ST.object_id = I.object_id AND ST.stats_id = I.index_id INNER JOIN sys.data_spaces DS ON I.data_space_id = DS.data_space_id INNER JOIN sys.filegroups FG ON I.data_space_id = FG.data_space_id LEFT OUTER JOIN (SELECT * FROM (SELECT IC2.object_id, IC2.index_id, STUFF((SELECT ', ' + C.name FROM sys.index_columns IC1 INNER 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, '') as IncludedColumns FROM sys.index_columns IC2 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
Using SQL Server 2016, this gives a complete list of all indexes, with an included dump of each table so you can see how the tables relate. It also shows columns included in covering indexes:
select t.name TableName, i.name IdxName, c.name ColName , ic.index_column_id ColPosition , i.type_desc Type , case when i.is_primary_key = 1 then 'Yes' else '' end [Primary?] , case when i.is_unique = 1 then 'Yes' else '' end [Unique?] , case when ic.is_included_column = 0 then '' else 'Yes - Included' end [CoveredColumn?] , 'indexes >>>>' [*indexes*], i.*, 'index_columns >>>>' [*index_columns*] , ic.*, 'tables >>>>' [*tables*] , t.*, 'columns >>>>' [*columns*], c.* from sys.index_columns ic join sys.tables t on t.object_id = ic.object_id join sys.columns c on c.object_id = t.object_id and c.column_id = ic.column_id join sys.indexes i on i.object_id = t.object_id and i.index_id = ic.index_id order by TableName, IdxName, ColPosition
sELECT TableName = t.name, IndexName = ind.name, --IndexId = ind.index_id, ColumnId = ic.index_column_id, ColumnName = col.name, key_ordinal, ind.type_desc --ind.*, --ic.*, --col.* FROM sys.indexes ind INNER JOIN sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id INNER JOIN sys.tables t ON ind.object_id = t.object_id WHERE ind.is_primary_key = 0 AND ind.is_unique = 0 AND ind.is_unique_constraint = 0 AND t.is_ms_shipped = 0 and t.name='CompanyReconciliation' --table name and key_ordinal>0 ORDER BY t.name, ind.name, ind.index_id, ic.index_column_id