2009-07-13 112 views
2

作为更改排序规则练习的一部分,我有一个索引列表(122),需要删除并重新创建。我怎样才能重新创建这些索引,而无需通过GUI并将其脚本编写到查询窗口中?从这个脚本为索引列表生成CREATE脚本

WITH indexCTE AS 
    ( 
    SELECT Table_Name, Column_Name, Collation_Name 
    FROM information_schema.columns 
    WHERE Collation_Name IS NOT NULL AND Collation_Name = 'Modern_Spanish_CI_AS' 
    ), 
    indexCTE2 AS 
    (
    SELECT i.Name [Index Name], OBJECT_NAME(i.object_ID) [Table Name], c.Name [Column Name] 
    FROM sys.indexes i 
    INNER JOIN sys.index_columns ic ON i.index_id = ic.index_id AND i.object_id = ic.object_id 
    INNER JOIN sys.columns c ON ic.column_id = c.column_id AND ic.object_id = c.OBJECT_ID 
    WHERE EXISTS (SELECT 1 FROM indexCTE t1 WHERE t1.Table_Name = OBJECT_NAME(i.object_ID) AND t1.Column_Name = c.Name) 
    ) SELECT * FROM indexCTE2 

正如你可能会说,我仍然获得

我的索引列表中的小DBA所以请耐心等待我!

谢谢!

回答

9

你很亲密,我会说 - 我试过这个,你可以验证这是否适用于你,并显示你预期的122个索引被重新创建?

UPDATE:增加了确定CLUSTERED与NONCLUSTERED索引类型的功能,并将INCLUDEd列添加到索引定义中。

WITH indexCTE AS 
(
    SELECT DISTINCT 
     i.index_id, i.name, i.object_id 
    FROM 
     sys.indexes i 
    INNER JOIN 
     sys.index_columns ic 
      ON i.index_id = ic.index_id AND i.object_id = ic.object_id 
    WHERE 
     EXISTS (SELECT * FROM sys.columns c 
       WHERE c.collation_name = 'Modern_Spanish_CI_AS' 
       AND c.column_id = ic.column_id AND c.object_id = ic.object_id) 
), 
indexCTE2 AS 
(
    SELECT 
     indexCTE.name 'IndexName', 
     OBJECT_NAME(indexCTE.object_ID) 'TableName', 
     CASE indexCTE.index_id 
      WHEN 1 THEN 'CLUSTERED' 
      ELSE 'NONCLUSTERED' 
     END AS 'IndexType', 
     (SELECT DISTINCT c.name + ',' 
     FROM 
      sys.columns c 
     INNER JOIN 
      sys.index_columns ic 
       ON c.object_id = ic.object_id AND ic.column_id = c.column_id AND ic.Is_Included_Column = 0 
     WHERE 
      indexCTE.OBJECT_ID = ic.object_id 
      AND indexCTE.index_id = ic.index_id 
     FOR XML PATH('') 
     ) ixcols, 
     ISNULL(
     (SELECT DISTINCT c.name + ',' 
     FROM 
      sys.columns c 
     INNER JOIN 
      sys.index_columns ic 
       ON c.object_id = ic.object_id AND ic.column_id = c.column_id AND ic.Is_Included_Column = 1 
     WHERE 
      indexCTE.OBJECT_ID = ic.object_id 
      AND indexCTE.index_id = ic.index_id 
     FOR XML PATH('') 
     ), '') includedcols 
    FROM 
     indexCTE 
) 
SELECT 
    'CREATE ' + IndexType + ' INDEX ' + IndexName + ' ON ' + TableName + 
     '(' + SUBSTRING(ixcols, 1, LEN(ixcols)-1) + 
     CASE LEN(includedcols) 
      WHEN 0 THEN ')' 
      ELSE ') INCLUDE (' + SUBSTRING(includedcols, 1, LEN(includedcols)-1) + ')' 
     END 
FROM 
    indexCTE2 
ORDER BY 
    TableName, IndexName 

您是否在寻找CREATE INDEX声明?

马克

+0

与此问题是我有一些索引是复合索引。其中一些还包括列或独特的等我不能只是重新创建它们。我需要复制每个索引的原始模式... – super9 2009-07-13 22:10:57

1
DECLARE @T_IndexInfo TABLE 
    (
     IndID NVARCHAR(128), 
     ObjectID NVARCHAR(128), 
     ColID NVARCHAR(128), 
     IndexName NVARCHAR(128), 
     TableName NVARCHAR(128), 
     ColumnName NVARCHAR(128), 
     KeyNo NVARCHAR(128), 
     ColType NVARCHAR(128) 
    ) 

INSERT INTO @T_IndexInfo 
     SELECT I.IndID, 
       SO.ID AS 'ObjectID', 
       SK.ColID, 
       I.Name AS 'IndexName', 
       SO.Name AS 'TableName', 
       SC.Name AS 'ColumnName', 
       Sk.KeyNo, 
       CASE WHEN Sk.KeyNo = 0 THEN 'Include' 
        ELSE 'Normal' 
       END AS 'ColType' 
     FROM sys.sysindexes I 
       INNER JOIN sys.sysobjects SO ON SO.ID = I.ID 
               AND SO.xtype = 'U' 
       INNER JOIN sys.sysindexkeys SK ON SK.IndID = I.IndID 
                AND SO.ID = SK.ID 
       INNER JOIN sys.syscolumns SC ON SC.ID = SO.ID 
               AND SC.ColID = SK.ColID 
     WHERE I.IndID > 0 
       AND I.IndID < 255 
       AND (I.Status & 64) = 0 
--    AND (I.status & 2048) <> 2048 /******** comment this if PK's also need to be recreated *****/ 
     ORDER BY SO.Name, 
       I.Name 

DECLARE @T_Final TABLE 
    (
     TableName NVARCHAR(128), 
     IndexName NVARCHAR(128), 
     NormalColumns NVARCHAR(MAX), 
     IncludedColumns NVARCHAR(MAX) 
    ) 

INSERT INTO @T_Final 
     SELECT DISTINCT 
       TableName, 
       IndexName, 
       STUFF((SELECT ',[' + ColumnName + ']' 
         FROM @T_IndexInfo 
         WHERE IndID = I.IndID 
           AND ObjectID = I.ObjectID 
           AND ColType = 'Normal' 
         ORDER BY KeyNo 
         FOR 
         XML PATH('') 
        ), 1, 1, '') AS 'NormalColumns', 
       STUFF((SELECT ',[' + ColumnName + ']' 
         FROM @T_IndexInfo 
         WHERE IndID = I.IndID 
           AND ObjectID = I.ObjectID 
           AND ColType = 'Include' 
         FOR 
         XML PATH('') 
        ), 1, 1, '') AS 'IncludedColumns' 
     FROM @T_IndexInfo I; 

WITH indexCTE AS 
    ( 
    SELECT Table_Name, Column_Name --, Collation_Name 
    FROM information_schema.columns 
    WHERE Collation_Name IS NOT NULL AND Collation_Name = 'Modern_Spanish_CI_AS' 
    ), 
    indexCTE2 AS 
    (
    SELECT i.Name [Index Name], OBJECT_NAME(i.object_ID) [Table Name], c.Name [Column Name] 
    FROM sys.indexes i 
    INNER JOIN sys.index_columns ic ON i.index_id = ic.index_id AND i.object_id = ic.object_id 
    INNER JOIN sys.columns c ON ic.column_id = c.column_id AND ic.object_id = c.OBJECT_ID 
    WHERE EXISTS (SELECT 1 FROM indexCTE t1 WHERE t1.Table_Name = OBJECT_NAME(i.object_ID) AND t1.Column_Name = c.Name) 
    ) 

SELECT IndexName, TableName, NormalColumns, IncludedColumns 
INTO #temp1 
FROM @T_Final z INNER JOIN indexCTE2 x ON z.IndexName = x.[Index Name] 

-- To generate CREATE INDEX SCRIPT 
SELECT 'CREATE INDEX [' + IndexName + '] ON [' + TableName + '].(' 
     + NormalColumns + ')' + CASE WHEN IncludedColumns IS NULL THEN '' 
            ELSE ' INCLUDE (' + IncludedColumns + ')' 
           END AS 'CreateScript' 
FROM #temp1 

-- To generate DROP INDEX SCRIPT 
SELECT 'DROP INDEX [' + TableName + '].[' + IndexName + ']' AS 'DropScript' 
FROM #temp1 

DROP TABLE#temp1中

0

这是一个有点题外话,但想到我会反正这提示:

如果您不想继续执行脚本在SQL Server Management Studio中,您可以创建一个runmyscripts.bat文件,包括像:

@echo off 

echo Execute Scripts... 

sqlcmd -i C:\Scripts\myscript1.sql 
sqlcmd -i C:\Scripts\myscript2.sql 

echo Scripts Complete. 
echo Press any button to exit. 
pause 
4

伟大的脚本马克。 我认为它唯一缺少的是每列上的升序或降序指标。我已经修改了您的脚本以包含索引列的case语句,以便在ASC或DESC中添加,具体取决于sys.index_columns视图的is_descending_key列。

WITH indexCTE AS 
(
    SELECT DISTINCT 
     i.index_id, i.name, i.object_id 
    FROM 
     sys.indexes i 
    INNER JOIN 
     sys.index_columns ic 
      ON i.index_id = ic.index_id AND i.object_id = ic.object_id 
    WHERE 
     EXISTS (SELECT * FROM sys.columns c 
       WHERE 
       c.collation_name = 'Modern_Spanish_CI_AS' 
       AND c.column_id = ic.column_id AND c.object_id = ic.object_id) 
), 
indexCTE2 AS 
(
    SELECT 
     indexCTE.name 'IndexName', 
     OBJECT_NAME(indexCTE.object_ID) 'TableName', 
     CASE indexCTE.index_id 
      WHEN 1 THEN 'CLUSTERED' 
      ELSE 'NONCLUSTERED' 
     END AS 'IndexType', 
     (SELECT CASE WHEN ic.is_descending_key = 1 THEN c.name + ' DESC ,' 
       ELSE c.name + ' ASC ,' 
       END 
     FROM 
      sys.columns c 
     INNER JOIN 
      sys.index_columns ic 
       ON c.object_id = ic.object_id AND ic.column_id = c.column_id AND ic.Is_Included_Column = 0 
     WHERE 
      indexCTE.OBJECT_ID = ic.object_id 
      AND indexCTE.index_id = ic.index_id 
     FOR XML PATH('') 
     ) ixcols, 
     ISNULL(
     (SELECT DISTINCT c.name + ',' 
     FROM 
      sys.columns c 
     INNER JOIN 
      sys.index_columns ic 
       ON c.object_id = ic.object_id AND ic.column_id = c.column_id AND ic.Is_Included_Column = 1 
     WHERE 
      indexCTE.OBJECT_ID = ic.object_id 
      AND indexCTE.index_id = ic.index_id 
     FOR XML PATH('') 
     ), '') includedcols 
    FROM 
     indexCTE 
) 
SELECT 
    'CREATE ' + IndexType + ' INDEX ' + IndexName + ' ON ' + TableName + 
     '(' + SUBSTRING(ixcols, 1, LEN(ixcols)-1) + 
     CASE LEN(includedcols) 
      WHEN 0 THEN ')' 
      ELSE ') INCLUDE (' + SUBSTRING(includedcols, 1, LEN(includedcols)-1) + ')' 
     END 
FROM 
    indexCTE2 
ORDER BY 
    TableName, IndexName 
0

TechNet有一个相对完整的解决方案。

调整查询到您的愿望:

  • SYS.TABLES在选择
  • 删除sys.views
  • 删除默认值/加一些有条件的地方