生成数据库中所有索引的脚本

时间:2012-02-01 01:51:50

标签: sql-server tsql indexing

我想生成数据库中所有索引的脚本(创建索引)。

我不希望索引脚本和create table脚本一起使用。我们如何在SQL Server(2005或2008)中生成它。群集和非群集索引需要单独的脚本。

7 个答案:

答案 0 :(得分:21)

这是excellent article SQL Server Central我已经使用过的。{/ p>

您可能更喜欢another

如果它不是您正在寻找的(排序,过滤),我确信编辑它们比从头开始更容易。

以下是第一个示例中略微更正的(2019)代码:

-- Get all existing indexes, but NOT the primary keys
DECLARE cIX CURSOR FOR
    SELECT OBJECT_NAME(SI.Object_ID), SI.Object_ID, SI.Name, SI.Index_ID
        FROM Sys.Indexes SI 
            LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC ON SI.Name = TC.CONSTRAINT_NAME AND OBJECT_NAME(SI.Object_ID) = TC.TABLE_NAME
        WHERE TC.CONSTRAINT_NAME IS NULL
            AND OBJECTPROPERTY(SI.Object_ID, 'IsUserTable') = 1
        ORDER BY OBJECT_NAME(SI.Object_ID), SI.Index_ID

DECLARE @IxTable SYSNAME
DECLARE @IxTableID INT
DECLARE @IxName SYSNAME
DECLARE @IxID INT

-- Loop through all indexes
OPEN cIX
FETCH NEXT FROM cIX INTO @IxTable, @IxTableID, @IxName, @IxID
WHILE (@@FETCH_STATUS = 0)
BEGIN
    DECLARE @IXSQL NVARCHAR(4000) SET @IXSQL = ''
    SET @IXSQL = 'CREATE '

    -- Check if the index is unique
    IF (INDEXPROPERTY(@IxTableID, @IxName, 'IsUnique') = 1)
        SET @IXSQL = @IXSQL + 'UNIQUE '
    -- Check if the index is clustered
    IF (INDEXPROPERTY(@IxTableID, @IxName, 'IsClustered') = 1)
        SET @IXSQL = @IXSQL + 'CLUSTERED '

    SET @IXSQL = @IXSQL + 'INDEX ' + @IxName + ' ON ' + @IxTable + '('

    -- Get all columns of the index
    DECLARE cIxColumn CURSOR FOR 
        SELECT SC.Name
        FROM Sys.Index_Columns IC
            JOIN Sys.Columns SC ON IC.Object_ID = SC.Object_ID AND IC.Column_ID = SC.Column_ID
        WHERE IC.Object_ID = @IxTableID AND Index_ID = @IxID
        ORDER BY IC.Index_Column_ID

    DECLARE @IxColumn SYSNAME
    DECLARE @IxFirstColumn BIT SET @IxFirstColumn = 1

    -- Loop throug all columns of the index and append them to the CREATE statement
    OPEN cIxColumn
    FETCH NEXT FROM cIxColumn INTO @IxColumn
    WHILE (@@FETCH_STATUS = 0)
    BEGIN
        IF (@IxFirstColumn = 1)
            SET @IxFirstColumn = 0
        ELSE
            SET @IXSQL = @IXSQL + ', '

        SET @IXSQL = @IXSQL + @IxColumn

        FETCH NEXT FROM cIxColumn INTO @IxColumn
    END
    CLOSE cIxColumn
    DEALLOCATE cIxColumn

    SET @IXSQL = @IXSQL + ')'
    -- Print out the CREATE statement for the index
    IF @IXSQL != '' BEGIN PRINT @IXSQL END

    FETCH NEXT FROM cIX INTO @IxTable, @IxTableID, @IxName, @IxID
END

CLOSE cIX
DEALLOCATE cIX

答案 1 :(得分:21)

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 I.Object_id = object_id('Person.Address') --Comment for all tables
           --AND I.name = 'IX_Address_PostalCode' --comment for all indexes 

答案 2 :(得分:5)

TSQL用于脚本编制数据库中的所有索引

这将编写脚本:

  1. 群集和非群集索引(包括筛选索引)
  2. 创建索引的文件组(如果未分区)
  3. 创建索引的分区方案(如果已分区)
  4. 如果索引是压缩的压缩设置 - 它是每个 如果表已分区,则进行分区
  5. 对于没有聚集索引的表,它们仍然会得到一个 结果中的行,注释表明它是一个堆
  6.     Select DB_NAME() AS database_name,
        sc.name + N'.' + t.name AS table_name,
        (SELECT MAX(user_reads) 
            FROM (VALUES (last_user_seek), (last_user_scan), (last_user_lookup)) AS value(user_reads)) AS last_user_read,
        last_user_update,
        CASE si.index_id WHEN 0 THEN N'/* No create statement (Heap) */'
        ELSE 
            CASE is_primary_key WHEN 1 THEN
                N'ALTER TABLE ' + QUOTENAME(sc.name) + N'.' + QUOTENAME(t.name) + N' ADD CONSTRAINT ' + QUOTENAME(si.name) + N' PRIMARY KEY ' +
                    CASE WHEN si.index_id > 1 THEN N'NON' ELSE N'' END + N'CLUSTERED '
                ELSE N'CREATE ' + 
                    CASE WHEN si.is_unique = 1 then N'UNIQUE ' ELSE N'' END +
                    CASE WHEN si.index_id > 1 THEN N'NON' ELSE N'' END + N'CLUSTERED ' +
                    N'INDEX ' + QUOTENAME(si.name) + N' ON ' + QUOTENAME(sc.name) + N'.' + QUOTENAME(t.name) + N' '
            END +
            /* key def */ N'(' + key_definition + N')' +
            /* includes */ CASE WHEN include_definition IS NOT NULL THEN 
                N' INCLUDE (' + include_definition + N')'
                ELSE N''
            END +
            /* filters */ CASE WHEN filter_definition IS NOT NULL THEN 
                N' WHERE ' + filter_definition ELSE N''
            END +
            /* with clause - compression goes here */
            CASE WHEN row_compression_partition_list IS NOT NULL OR page_compression_partition_list IS NOT NULL 
                THEN N' WITH (' +
                    CASE WHEN row_compression_partition_list IS NOT NULL THEN
                        N'DATA_COMPRESSION = ROW ' + CASE WHEN psc.name IS NULL THEN N'' ELSE + N' ON PARTITIONS (' + row_compression_partition_list + N')' END
                    ELSE N'' END +
                    CASE WHEN row_compression_partition_list IS NOT NULL AND page_compression_partition_list IS NOT NULL THEN N', ' ELSE N'' END +
                    CASE WHEN page_compression_partition_list IS NOT NULL THEN
                        N'DATA_COMPRESSION = PAGE ' + CASE WHEN psc.name IS NULL THEN N'' ELSE + N' ON PARTITIONS (' + page_compression_partition_list + N')' END
                    ELSE N'' END
                + N')'
                ELSE N''
            END +
            /* ON where? filegroup? partition scheme? */
            ' ON ' + CASE WHEN psc.name is null 
                THEN ISNULL(QUOTENAME(fg.name),N'')
                ELSE psc.name + N' (' + partitioning_column.column_name + N')' 
                END
            + N';'
        END AS index_create_statement,
        si.index_id,
        si.name AS index_name,
        partition_sums.reserved_in_row_GB,
        partition_sums.reserved_LOB_GB,
        partition_sums.row_count,
        stat.user_seeks,
        stat.user_scans,
        stat.user_lookups,
        user_updates AS queries_that_modified,
        partition_sums.partition_count,
        si.allow_page_locks,
        si.allow_row_locks,
        si.is_hypothetical,
        si.has_filter,
        si.fill_factor,
        si.is_unique,
        ISNULL(pf.name, '/* Not partitioned */') AS partition_function,
        ISNULL(psc.name, fg.name) AS partition_scheme_or_filegroup,
        t.create_date AS table_created_date,
        t.modify_date AS table_modify_date
    FROM sys.indexes AS si
    JOIN sys.tables AS t ON si.object_id=t.object_id
    JOIN sys.schemas AS sc ON t.schema_id=sc.schema_id
    LEFT JOIN sys.dm_db_index_usage_stats AS stat ON 
        stat.database_id = DB_ID() 
        and si.object_id=stat.object_id 
        and si.index_id=stat.index_id
    LEFT JOIN sys.partition_schemes AS psc ON si.data_space_id=psc.data_space_id
    LEFT JOIN sys.partition_functions AS pf ON psc.function_id=pf.function_id
    LEFT JOIN sys.filegroups AS fg ON si.data_space_id=fg.data_space_id
    /* Key list */ OUTER APPLY ( SELECT STUFF (
        (SELECT N', ' + QUOTENAME(c.name) +
            CASE ic.is_descending_key WHEN 1 then N' DESC' ELSE N'' END
        FROM sys.index_columns AS ic 
        JOIN sys.columns AS c ON 
            ic.column_id=c.column_id  
            and ic.object_id=c.object_id
        WHERE ic.object_id = si.object_id
            and ic.index_id=si.index_id
            and ic.key_ordinal > 0
        ORDER BY ic.key_ordinal FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,2,'')) AS keys ( key_definition )
    /* Partitioning Ordinal */ OUTER APPLY (
        SELECT MAX(QUOTENAME(c.name)) AS column_name
        FROM sys.index_columns AS ic 
        JOIN sys.columns AS c ON 
            ic.column_id=c.column_id  
            and ic.object_id=c.object_id
        WHERE ic.object_id = si.object_id
            and ic.index_id=si.index_id
            and ic.partition_ordinal = 1) AS partitioning_column
    /* Include list */ OUTER APPLY ( SELECT STUFF (
        (SELECT N', ' + QUOTENAME(c.name)
        FROM sys.index_columns AS ic 
        JOIN sys.columns AS c ON 
            ic.column_id=c.column_id  
            and ic.object_id=c.object_id
        WHERE ic.object_id = si.object_id
            and ic.index_id=si.index_id
            and ic.is_included_column = 1
        ORDER BY c.name FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,2,'')) AS includes ( include_definition )
    /* Partitions */ OUTER APPLY ( 
        SELECT 
            COUNT(*) AS partition_count,
            CAST(SUM(ps.in_row_reserved_page_count)*8./1024./1024. AS NUMERIC(32,1)) AS reserved_in_row_GB,
            CAST(SUM(ps.lob_reserved_page_count)*8./1024./1024. AS NUMERIC(32,1)) AS reserved_LOB_GB,
            SUM(ps.row_count) AS row_count
        FROM sys.partitions AS p
        JOIN sys.dm_db_partition_stats AS ps ON
            p.partition_id=ps.partition_id
        WHERE p.object_id = si.object_id
            and p.index_id=si.index_id
        ) AS partition_sums
    /* row compression list by partition */ OUTER APPLY ( SELECT STUFF (
        (SELECT N', ' + CAST(p.partition_number AS VARCHAR(32))
        FROM sys.partitions AS p
        WHERE p.object_id = si.object_id
            and p.index_id=si.index_id
            and p.data_compression = 1
        ORDER BY p.partition_number FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,2,'')) AS row_compression_clause ( row_compression_partition_list )
    /* data compression list by partition */ OUTER APPLY ( SELECT STUFF (
        (SELECT N', ' + CAST(p.partition_number AS VARCHAR(32))
        FROM sys.partitions AS p
        WHERE p.object_id = si.object_id
            and p.index_id=si.index_id
            and p.data_compression = 2
        ORDER BY p.partition_number FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,2,'')) AS page_compression_clause ( page_compression_partition_list )
    WHERE 
        si.type IN (0,1,2) /* heap, clustered, nonclustered */
    ORDER BY table_name, si.index_id
        OPTION (RECOMPILE);
    GO
    

答案 3 :(得分:1)

我可能会建议一种方法:

  1. 编写表格,没有标记(索引)。
  2. 在其他数据库中重新创建表
  3. 使用sql comparer工具,使索引基于两个数据库创建脚本 (也许如果你有这样的工具,那个工具可能已经有了这个功能。)

答案 4 :(得分:1)

这是为SQL Server 2017及更高版本更新的更简洁的版本,现在包括视图索引:

-- remove sys.tables or sys.views from this CTE as needed
with base_objects as
(   Select Name, object_ID, schema_ID, type_desc
    from sys.tables
    union all
    Select  Name, object_ID, schema_ID, type_desc
    from sys.views
)
  
SELECT
    [Table_name] 
,   tbl.[type_desc]
,   [Table_object_ID] 
,   [Index_name] 
,   idx.Index_ID
,   [Definition] = 'CREATE ' + [unique] + idx.[type_desc] + ' INDEX [' + index_name + '] ON ' 
            + SCHEMA_NAME(schema_id) + '.' + Table_name 
            + ' ( ' +  key_cols + ' )'
            + isnull(' INCLUDE ( ' + inc_cols + ' ) ','')
            + ' WITH (' + [options] + ' )'
            + ' ON [' + dat.name + ']' +  CHAR(13) + CHAR(10) + ' GO'
FROM Sys.Indexes idx
    join base_objects tbl
        on tbl.object_id = idx.object_ID
    join sys.stats stat
        ON  stat.object_id = idx.object_id
        AND stat.stats_id = idx.index_id
    JOIN sys.data_spaces dat
        ON  idx.data_space_id = dat.data_space_id
    cross apply (Select
        [Table_name] = OBJECT_NAME(idx.Object_ID)
    ,   [Table_object_ID] = idx.Object_ID
    ,   [Index_name] = idx.Name
    ,   [unique] = case when is_unique = 1 then 'UNIQUE ' else '' end

    ) labels
    cross apply (Select
        key_cols = string_agg(key_col_name, ', ') collate DATABASE_DEFAULT
    ,   inc_cols = string_agg(inc_col_name, ', ') collate DATABASE_DEFAULT
        from
            sys.index_columns sub_ic
            join sys.columns sub_col
                on sub_col.object_ID = sub_ic.object_id and sub_col.column_id = sub_ic.column_id
            cross apply (Select
                key_col_name = case when is_included_column = 0 then sub_col.name end
            ,   inc_col_name = case when is_included_column = 1 then sub_col.name end
            ) key_inc
        where sub_ic.object_id = idx.object_id and sub_ic.index_id = idx.index_id
            and is_included_column = 0
    ) cols
    cross apply (Select
        options = string_agg([option] + on_off, ', ')
        from (values
          ( 'PAD_INDEX = ' , idx.is_padded)
        , ( 'FILLFACTOR = ', nullif(idx.fill_factor, 0))
        , ( 'IGNORE_DUP_KEY = ', idx.ignore_dup_key)
        , ( 'STATISTICS_NORECOMPUTE = ', stat.no_recompute)
        , ( 'ALLOW_ROW_LOCKS = ', idx.allow_row_locks)
        , ( 'ALLOW_PAGE_LOCKS = ', idx.allow_page_locks)
        ) opts([option], val)
        cross apply (Select
            on_off = case val when 1 then 'ON' when 0 then 'OFF' else CONVERT( CHAR(5), val) end
        ) on_off_calc
    ) options_calc

where idx.name is not null

答案 5 :(得分:0)

我使用以下内容(包括模式和“如果不存在”)来生成Visual Studio中数据库项目所需的部署后脚本:

-- Get all existing indexes, but NOT the primary keys
DECLARE cIX CURSOR FOR
   SELECT OBJECT_NAME(SI.Object_ID), SI.Object_ID, SI.Name, SI.Index_ID, SC.name
      FROM Sys.Indexes SI 
         LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC ON SI.Name = TC.CONSTRAINT_NAME AND OBJECT_NAME(SI.Object_ID) = TC.TABLE_NAME
         LEFT JOIN SYS.tables TB ON (OBJECT_NAME(SI.Object_ID) = TB.name)
         LEFT JOIN SYS.schemas SC ON (TB.schema_id=SC.schema_id)
      WHERE TC.CONSTRAINT_NAME IS NULL
         AND OBJECTPROPERTY(SI.Object_ID, 'IsUserTable') = 1
      ORDER BY OBJECT_NAME(SI.Object_ID), SI.Index_ID

DECLARE @IxTable SYSNAME
DECLARE @IxTableID INT
DECLARE @IxName SYSNAME
DECLARE @IxID INT
DECLARE @IxSchema SYSNAME
DECLARE @PKSQL VARCHAR(50)

-- Loop through all indexes
OPEN cIX
FETCH NEXT FROM cIX INTO @IxTable, @IxTableID, @IxName, @IxID, @IxSchema
WHILE (@@FETCH_STATUS = 0)
BEGIN
   DECLARE @IXSQL NVARCHAR(4000) 
   SET @PKSQL = ''
   SET @IXSQL = 'IF NOT EXISTS(SELECT TOP 1 1 FROM sys.indexes WHERE name=''' + @IxName + ''' AND object_id = OBJECT_ID(''' + @IxSchema + '.' + @IxTable + '''))'
   SET @IXSQL = @IXSQL + CHAR(13) + CHAR(10)
   SET @IXSQL = @IXSQL + 'BEGIN'
   SET @IXSQL = @IXSQL + CHAR(13) + CHAR(10)
   SET @IXSQL = @IXSQL + CHAR(9) + 'CREATE '

   -- Check if the index is unique
   IF (INDEXPROPERTY(@IxTableID, @IxName, 'IsUnique') = 1)
      SET @IXSQL = @IXSQL + 'UNIQUE '
   -- Check if the index is clustered
   IF (INDEXPROPERTY(@IxTableID, @IxName, 'IsClustered') = 1)
      SET @IXSQL = @IXSQL + 'CLUSTERED '

   SET @IXSQL = @IXSQL + 'INDEX [' + @IxName + '] ON [' + @IxSchema + '].[' + @IxTable + ']('

   -- Get all columns of the index
   DECLARE cIxColumn CURSOR FOR 
      SELECT SC.Name
      FROM Sys.Index_Columns IC
         JOIN Sys.Columns SC ON IC.Object_ID = SC.Object_ID AND IC.Column_ID = SC.Column_ID
      WHERE IC.Object_ID = @IxTableID AND Index_ID = @IxID
      ORDER BY IC.Index_Column_ID

   DECLARE @IxColumn SYSNAME
   DECLARE @IxFirstColumn BIT, @ColumnCount INT 
   SET @IxFirstColumn = 1
   SET @ColumnCount = 0

   -- Loop throug all columns of the index and append them to the CREATE statement
   OPEN cIxColumn
   FETCH NEXT FROM cIxColumn INTO @IxColumn
   WHILE (@@FETCH_STATUS = 0)
   BEGIN
      IF (@ColumnCount < 16)
      BEGIN
          IF (@IxFirstColumn = 1)
             SET @IxFirstColumn = 0
          ELSE
             SET @IXSQL = @IXSQL + ', '

          SET @IXSQL = @IXSQL + '[' + @IxColumn + ']'
          SET @ColumnCount = @ColumnCount + 1
      END
      FETCH NEXT FROM cIxColumn INTO @IxColumn
   END
   CLOSE cIxColumn
   DEALLOCATE cIxColumn

   SET @IXSQL = @IXSQL + ')'

   SET @IXSQL = @IXSQL + CHAR(13) + CHAR(10)
   SET @IXSQL = @IXSQL + 'END'
   -- Print out the CREATE statement for the index
   IF(LEN(@IXSQL) > 10)
    PRINT @IXSQL

   FETCH NEXT FROM cIX INTO @IxTable, @IxTableID, @IxName, @IxID, @IxSchema
END

CLOSE cIX
DEALLOCATE cIX

答案 6 :(得分:0)

我知道这个线程非常老,这不是世界上最漂亮的东西,但是我需要一个存储的proc,它将为指定的数据库生成索引,并且在互联网上找不到它,所以这就是我创建了。

此存储过程将数据库名称作为参数,然后生成tsql以创建数据库中的所有索引。它考虑了索引选项,架构,所有者和INCLUDE列。

```
use dbatools
go

create procedure usp_script_index @dbname sysname
as

declare @SchemaName varchar(100)
declare @TableName varchar(256)
declare @IndexName varchar(256)
declare @ColumnName varchar(100)
declare @is_unique varchar(100)
declare @IndexTypeDesc varchar(100)
declare @FileGroupName varchar(100)
declare @is_disabled varchar(100)
declare @IndexOptions varchar(max)
declare @IndexColumnId int
declare @IsDescendingKey int 
declare @IsIncludedColumn int
declare @TSQLScripCreationIndex varchar(max)
declare @TSQLScripDisableIndex varchar(max)

 IF DB_ID(@dbname) IS NULL  /*Validate the database name exists*/
       BEGIN
       RAISERROR('Invalid Database Name passed',16,1)
       RETURN
       END

set nocount on 

create table #tbls (
sch_name sysname,
tbl_name sysname,
index_name sysname,
unique_flag varchar(20),
type_desc varchar(20),
indexoptions varchar(500),
is_disabled int,
fileGroupName sysname
)

DECLARE @dynsql nvarchar(max)  
declare @dynsql2 nvarchar(max)

 /*Use QUOTENAME to correctly escape any special characters*/
SET @dynsql = N'insert #tbls select 
schema_name(t.schema_id) [sch_name], 
t.name as tbl_name, 
ix.name as index_name,
 case when ix.is_unique = 1 then ''UNIQUE '' else '''' END as unique_flag
 , ix.type_desc,
 case when ix.is_padded=1 then ''PAD_INDEX = ON, '' else ''PAD_INDEX = OFF, '' end
 + case when ix.allow_page_locks=1 then ''ALLOW_PAGE_LOCKS = ON, '' else ''ALLOW_PAGE_LOCKS = OFF, '' end
 + case when ix.allow_row_locks=1 then  ''ALLOW_ROW_LOCKS = ON, '' else ''ALLOW_ROW_LOCKS = OFF, '' end
 + case when INDEXPROPERTY(t.object_id, ix.name, ''IsStatistics'') = 1 then ''STATISTICS_NORECOMPUTE = ON, '' 
 else ''STATISTICS_NORECOMPUTE = OFF, '' end
 + case when ix.ignore_dup_key=1 then ''IGNORE_DUP_KEY = ON, '' else ''IGNORE_DUP_KEY = OFF, '' end
 + ''SORT_IN_TEMPDB = OFF, FILLFACTOR ='' + CAST(ix.fill_factor AS VARCHAR(3)) AS IndexOptions
 , ix.is_disabled , FILEGROUP_NAME(ix.data_space_id) FileGroupName
 from ' + @dbname +'.sys.tables t 
 inner join ' + @dbname +'.sys.indexes ix on t.object_id=ix.object_id
 where ix.type>0 and ix.is_primary_key=0 and ix.is_unique_constraint=0 
 and t.is_ms_shipped=0 and t.name<>''sysdiagrams''
 order by schema_name(t.schema_id), t.name, ix.name'

 exec sp_executesql @dynsql

print 'use '+ @dbname + char(10) +'go' +char(10) 

declare CursorIndex cursor for select sch_name, tbl_name, index_name,unique_flag, type_desc, indexoptions,is_disabled,fileGroupName from #tbls

open CursorIndex
fetch next from CursorIndex into  @SchemaName, @TableName, @IndexName, @is_unique, @IndexTypeDesc, @IndexOptions,@is_disabled, @FileGroupName

while (@@fetch_status=0)
begin
 declare @IndexColumns varchar(max)
 declare @IncludedColumns varchar(max)

 set @IndexColumns=''
 set @IncludedColumns=''

 create table #cols
(
    column_name sysname,
    is_descending_key int,
    is_included_column int
)

 SET @dynsql2 = N' insert #cols
  select col.name as column_name, ixc.is_descending_key, ixc.is_included_column
  from '+ @dbname + '.sys.tables tb 
  inner join ' +@dbname +'.sys.indexes ix on tb.object_id=ix.object_id
  inner join ' +@dbname +'.sys.index_columns ixc on ix.object_id=ixc.object_id and ix.index_id= ixc.index_id
  inner join ' +@dbname +'.sys.columns col on ixc.object_id =col.object_id  and ixc.column_id=col.column_id
  where ix.type>0 and (ix.is_primary_key=0 or ix.is_unique_constraint=0)
  and schema_name(tb.schema_id)=''' + @SchemaName + ''' and tb.name= ''' + @TableName + ''' and ix.name=''' + @IndexName + ''' order by ixc.index_column_id '

 --print @dynsql2
 exec sp_executesql @dynsql2

 declare CursorIndexColumn cursor for select column_name,is_descending_key,is_included_column from #cols

 open CursorIndexColumn 
 fetch next from CursorIndexColumn into  @ColumnName, @IsDescendingKey, @IsIncludedColumn

 while (@@fetch_status=0)
 begin
  if @IsIncludedColumn=0 
   set @IndexColumns=@IndexColumns + @ColumnName  + case when @IsDescendingKey=1  then ' DESC, ' else  ' ASC, ' end
  else 
   set @IncludedColumns=@IncludedColumns  + @ColumnName  +', ' 

  fetch next from CursorIndexColumn into @ColumnName, @IsDescendingKey, @IsIncludedColumn
 end

 drop table #cols
 close CursorIndexColumn
 deallocate CursorIndexColumn

 set @IndexColumns = substring(@IndexColumns, 1, len(@IndexColumns)-1)
 set @IncludedColumns = case when len(@IncludedColumns) >0 then substring(@IncludedColumns, 1, len(@IncludedColumns)-1) else '' end
 --  print @IndexColumns
 --  print @IncludedColumns

 set @TSQLScripCreationIndex =''
 set @TSQLScripDisableIndex =''
 set @TSQLScripCreationIndex='CREATE '+ @is_unique  +@IndexTypeDesc + ' INDEX ' +QUOTENAME(@IndexName)+' ON ' + QUOTENAME(@SchemaName) +'.'+ QUOTENAME(@TableName)+ '('+@IndexColumns+') '+ 
  case when len(@IncludedColumns)>0 then CHAR(13) +'INCLUDE (' + @IncludedColumns+ ')' else '' end + CHAR(13)+'WITH (' + @IndexOptions+ ') ON ' + QUOTENAME(@FileGroupName) + ';'  

 if @is_disabled=1 
  set  @TSQLScripDisableIndex=  CHAR(13) +'ALTER INDEX ' +QUOTENAME(@IndexName) + ' ON ' + QUOTENAME(@SchemaName) +'.'+ QUOTENAME(@TableName) + ' DISABLE;' + CHAR(13) 

 print @TSQLScripCreationIndex
 print @TSQLScripDisableIndex

 fetch next from CursorIndex into  @SchemaName, @TableName, @IndexName, @is_unique, @IndexTypeDesc, @IndexOptions,@is_disabled, @FileGroupName

end
close CursorIndex
deallocate CursorIndex
drop table #tbls

go
```