sqlsql-server-2005

Generate CREATE scripts for a list of indexes


As part of a collation changing exercise, I have a list of indexes (122) that needs to be dropped and then re-created. How can I re-create these indexes without having to go through the GUI and scripting it to a query window each time?

My list of indexes is obtained from this script

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

As you can probably tell, I'm still a Jr. DBA so please be patient with me!

Thanks!


Solution

  • You're pretty close, I'd say - I tried this, can you verify if this works for you and shows you the expected 122 indices to be recreated??

    UPDATE: added functionality to determine CLUSTERED vs. NONCLUSTERED index type, and to add INCLUDEd columns to the index definition.

    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
    

    Do you get the CREATE INDEX statements you're looking for??

    Marc