2009-07-13 109 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
  • 刪除默認值/加一些有條件的地方