zoukankan      html  css  js  c++  java
  • 根据表名和列名获取关联index的创建脚本

    需求背景:

    因为index的命名不规范,有时候很难判断,相关字段上有index

    针对以上需求,写了以下脚本来获取相关信息


    如果创建一个index

    use [lynntest]
    go
    create index ix_abc on [dbo].[tb] (indate,ca)include(flag)with(fillfactor=85)

    下面使用脚本获取结果

    /*
    desc:get table's crate index script
    */
    DECLARE
    @idxTableName SYSNAME,
    @idxTableID INT,
    @idxname SYSNAME,
    @idxid INT,
    @colCount INT,
    @colCountMinusIncludedColumns INT,
    @IxColumn SYSNAME,
    @IxFirstColumn BIT,
    @ColumnIDInTable INT,
    @ColumnIDInIndex INT,
    @IsIncludedColumn INT,
    @sIncludeCols VARCHAR(MAX),
    @sIndexCols VARCHAR(MAX),
    @sSQL VARCHAR(MAX),
    @sParamSQL VARCHAR(MAX),
    @sFilterSQL VARCHAR(MAX),
    @location SYSNAME,
    @IndexCount INT,
    @CurrentIndex INT,
    @CurrentCol INT,
    @Name VARCHAR(128),
    @IsPrimaryKey TINYINT,
    @Fillfactor INT,
    @FilterDefinition VARCHAR(MAX),
    @IsClustered BIT ,
    @S varchar(max),
    @X xml
    
    SET @S = 'tb,ca'  --input tbname,columnname
    
    
    IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE id = object_id(N'[tempdb].[dbo].[#TabColTab]'))
    DROP TABLE [dbo].[#TabColTab]
    
    CREATE TABLE #TabColTab
    (
         TabName sysname
        ,ColName sysname
    )
    
    IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE id = object_id(N'[tempdb].[dbo].[#TabIdxTab]'))
    DROP TABLE [dbo].[#TabIdxTab]
     
    
    
    CREATE TABLE #TabIdxTab
    (
         TabName sysname
        ,IndexName sysname
    )
    
    
    SELECT
          @S = N'<root><col>' + REPLACE(@s,CHAR(10),N'</col><col>') + N'</col></root>',
                @X = CONVERT(xml,@s)
    
    ;WITH CTE AS(
          SELECT
                            REPLACE(REPLACE(REPLACE(REPLACE(col,CHAR(10),N''),CHAR(13),N''),CHAR(9),N''),',','.') AS COL
          FROM
          (
                            SELECT 
                                              REPLACE(RTRIM(LTRIM(T.c.value(N'(text())[1]',N'nvarchar(300)'))),CHAR(10),N'') AS col
                            FROM @X.nodes('/root/col') T(c)
          )A
          WHERE A.col IS NOT NULL
    )
    ,CTE2 AS(
          SELECT
                TabName = PARSENAME(COL,2),
                ColName = PARSENAME(COL,1)
          FROM CTE
    )
    
    INSERT INTO [#TabColTab] 
    SELECT 
        * 
    FROM CTE2
    
    DECLARE @TabName1 sysname
           ,@ColName1 sysname
    DECLARE Tab_Cursor CURSOR 
    FOR 
    SELECT 
        TabName
       ,ColName 
    FROM #TabColTab
    
    OPEN Tab_Cursor;
    
    FETCH NEXT FROM Tab_Cursor INTO @TabName1
                                     ,@ColName1;
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
        
        INSERT INTO #TabIdxTab    
        SELECT  
            OBJECT_NAME(A.OBJECT_ID)    AS TabName 
           ,A.name AS index_name  
        FROM sys.indexes A JOIN sys.index_columns B ON B.OBJECT_ID = A.OBJECT_ID AND B.index_id = A.index_id JOIN sys.columns C ON C.OBJECT_ID = B.OBJECT_ID AND C.column_id = B.column_id 
        WHERE 
            a.OBJECT_ID=OBJECT_ID(@tabname1) 
            AND c.name=@colname1
        FETCH NEXT FROM Tab_Cursor INTO @TabName1
                                         ,@ColName1;
        END
        CLOSE Tab_Cursor;
        DEALLOCATE Tab_Cursor;
    
    
    IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE id = object_id(N'[tempdb].[dbo].[#IndexSQL]'))
    DROP TABLE [dbo].[#IndexSQL]
    
    CREATE TABLE #IndexSQL
    ( TableName VARCHAR(128) NOT NULL
     ,IndexName VARCHAR(128) NOT NULL
     ,IsClustered BIT NOT NULL
     ,IsPrimaryKey BIT NOT NULL
     ,IndexCreateSQL VARCHAR(max) NOT NULL
    )
    
    
    IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE id = object_id(N'[tempdb].[dbo].[#IndexListing]'))
    DROP TABLE [dbo].[#IndexListing]
    
    CREATE TABLE #IndexListing
    (
    [IndexListingID] INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
    [TableName] SYSNAME COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [ObjectID] INT NOT NULL,
    [IndexName] SYSNAME COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [IndexID] INT NOT NULL,
    [IsPrimaryKey] TINYINT NOT NULL,
    [FillFactor] INT,
    [FilterDefinition] NVARCHAR(MAX) NULL
    )
    
    IF EXISTS (SELECT * FROM tempdb.dbo.sysobjects WHERE id = object_id(N'[tempdb].[dbo].[#ColumnListing]'))
    DROP TABLE [dbo].[#ColumnListing]
    
    CREATE TABLE #ColumnListing
    (
    [ColumnListingID] INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
    [ColumnIDInTable] INT NOT NULL,
    [Name] SYSNAME COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [ColumnIDInIndex] INT NOT NULL,
    [IsIncludedColumn] BIT NULL
    )
    
    INSERT INTO #IndexListing( [TableName], [ObjectID], [IndexName], [IndexID], [IsPrimaryKey], [FILLFACTOR], [FilterDefinition] )
    SELECT OBJECT_NAME(si.object_id), si.object_id, si.name, si.index_id, si.Is_Primary_Key, si.Fill_Factor, si.filter_definition
    FROM sys.indexes si
    LEFT OUTER JOIN information_schema.table_constraints tc ON si.name = tc.constraint_name AND OBJECT_NAME(si.object_id) = tc.table_name
    WHERE OBJECTPROPERTY(si.object_id, 'IsUserTable') = 1
    ORDER BY OBJECT_NAME(si.object_id), si.index_id
    
    SELECT @IndexCount = @@ROWCOUNT, @CurrentIndex = 1
    
    WHILE @CurrentIndex <= @IndexCount
    BEGIN
    
        SELECT @idxTableName = [TableName],
        @idxTableID = [ObjectID],
        @idxname = [IndexName],
        @idxid = [IndexID],
        @IsPrimaryKey = [IsPrimaryKey],
        @FillFactor = [FILLFACTOR],
        @FilterDefinition = [FilterDefinition]
        FROM #IndexListing
        WHERE [IndexListingID] = @CurrentIndex
    
        -- So - it is either an index or a constraint
        -- Check if the index is unique
        IF (@IsPrimaryKey = 1)
        BEGIN
         SET @sSQL = 'ALTER TABLE [dbo].[' + @idxTableName + '] ADD CONSTRAINT [' + @idxname + '] PRIMARY KEY '
         -- Check if the index is clustered
         IF (INDEXPROPERTY(@idxTableID, @idxname, 'IsClustered') = 0)
         BEGIN
         SET @sSQL = @sSQL + 'NON'
         SET @IsClustered = 0
         END
         ELSE
         BEGIN
         SET @IsClustered = 1
         END
         SET @sSQL = @sSQL + 'CLUSTERED' + CHAR(13) + '(' + CHAR(13)
        END
        ELSE
        BEGIN
         SET @sSQL = 'CREATE '
         -- Check if the index is unique
         IF (INDEXPROPERTY(@idxTableID, @idxname, 'IsUnique') = 1)
         BEGIN
         SET @sSQL = @sSQL + 'UNIQUE '
         END
         -- Check if the index is clustered
         IF (INDEXPROPERTY(@idxTableID, @idxname, 'IsClustered') = 1)
         BEGIN
         SET @sSQL = @sSQL + 'CLUSTERED '
         SET @IsClustered = 1
         END
         ELSE
         BEGIN
         SET @IsClustered = 0
         END
    
         SELECT
         @sSQL = @sSQL + 'INDEX [' + @idxname + '] ON [dbo].[' + @idxTableName + ']' + CHAR(13) + '(' + CHAR(13),
         @colCount = 0,
         @colCountMinusIncludedColumns = 0
        END
    
        -- Get the nuthe mber of cols in the index
        SELECT @colCount = COUNT(*),
               @colCountMinusIncludedColumns = SUM(CASE ic.is_included_column WHEN 0 THEN 1 ELSE 0 END)
        FROM sys.index_columns ic
        INNER JOIN sys.columns sc ON ic.object_id = sc.object_id AND ic.column_id = sc.column_id
        WHERE ic.object_id = @idxtableid AND index_id = @idxid
    
        -- Get the file group info
        SELECT @location = f.[name]
        FROM sys.indexes i
        INNER JOIN sys.filegroups f ON i.data_space_id = f.data_space_id
        INNER JOIN sys.all_objects o ON i.[object_id] = o.[object_id]
        WHERE o.object_id = @idxTableID AND i.index_id = @idxid
    
        -- Get all columns of the index
        INSERT INTO #ColumnListing( [ColumnIDInTable], [Name], [ColumnIDInIndex],[IsIncludedColumn] )
        SELECT sc.column_id, sc.name, ic.index_column_id, ic.is_included_column
        FROM sys.index_columns ic
        INNER JOIN sys.columns sc ON ic.object_id = sc.object_id AND ic.column_id = sc.column_id
        WHERE ic.object_id = @idxTableID AND index_id = @idxid
        ORDER BY ic.index_column_id
    
        IF @@ROWCOUNT > 0
        BEGIN
    
        SELECT @CurrentCol = 1
        SELECT @IxFirstColumn = 1, @sIncludeCols = '', @sIndexCols = ''
        
        WHILE @CurrentCol <= @ColCount
        BEGIN
            SELECT @ColumnIDInTable = ColumnIDInTable,
            @Name = Name,
            @ColumnIDInIndex = ColumnIDInIndex,
            @IsIncludedColumn = IsIncludedColumn
            FROM #ColumnListing
            WHERE [ColumnListingID] = @CurrentCol
    
            IF @IsIncludedColumn = 0
            BEGIN
    
                SELECT @sIndexCols = CHAR(9) + @sIndexCols + '[' + @Name + '] '
    
                IF (INDEXKEY_PROPERTY (@idxTableID,@idxid,@ColumnIDInIndex,'IsDescending')) = 0
                    BEGIN
                    SET @sIndexCols = @sIndexCols + ' ASC '
                    END
                ELSE
                    BEGIN
                    SET @sIndexCols = @sIndexCols + ' DESC '
                    END
    
                IF @CurrentCol < @colCountMinusIncludedColumns
                    BEGIN
                    SET @sIndexCols = @sIndexCols + ', '
                    END
    
            END
            ELSE
            BEGIN
                -- Check for any include columns
                IF LEN(@sIncludeCols) > 0
                    BEGIN
                    SET @sIncludeCols = @sIncludeCols + ','
                    END
    
                SELECT @sIncludeCols = @sIncludeCols + '[' + @Name + ']'
    
            END
    
                SET @CurrentCol = @CurrentCol + 1
        END
    
        TRUNCATE TABLE #ColumnListing
        --append to the result
        IF LEN(@sIncludeCols) > 0
            SET @sIndexCols = @sSQL + @sIndexCols + CHAR(13) + ') ' + ' INCLUDE ( ' + @sIncludeCols + ' ) '
        ELSE
            SET @sIndexCols = @sSQL + @sIndexCols + CHAR(13) + ') '
    
        -- Add filtering
        IF @FilterDefinition IS NOT NULL
            SET @sFilterSQL = ' WHERE ' + @FilterDefinition + ' ' + CHAR(13)
        ELSE
            SET @sFilterSQL = ''
    
        -- Build the options
        SET @sParamSQL = ''
    
    
        -- Fillfactor 0 is actually not a valid percentage on SQL 2008 R2
        IF ISNULL( @FillFactor, 90 ) <> 0 
         SET @sParamSQL = @sParamSQL + ' WITH (FILLFACTOR = ' + CAST( ISNULL( @FillFactor, 90 ) AS VARCHAR(3) ) +')'
    
    
    
    
        SET @sSQL = @sIndexCols + CHAR(13) + @sFilterSQL + CHAR(13) + @sParamSQL  
    
        -- 2008 R2 allows ON [filegroup] for primary keys as well, negating the old "IF THE INDEX IS NOT A PRIMARY KEY - ADD THIS - ELSE DO NOT" IsPrimaryKey IF statement
        SET @sSQL = @sSQL + ' ON [' + @location + ']'
    
        --PRINT @sIndexCols + CHAR(13)
        INSERT INTO #IndexSQL (TableName, IndexName, IsClustered, IsPrimaryKey, IndexCreateSQL) VALUES (@idxTableName, @idxName, @IsClustered, @IsPrimaryKey, @sSQL)
    
        END
    
        SET @CurrentIndex = @CurrentIndex + 1
    END
    
    
    
    
    SELECT a.* FROM #IndexSQL as a inner join #TabIdxTab as b on a.TableName=b.tabname and a.indexname=b.indexname
     
    View Code

    结果如图


    CREATE INDEX [ix_abc] ON [dbo].[tb] ( [indate] ASC , [ca] ASC ) INCLUDE ( [flag] ) WITH (FILLFACTOR = 85) ON [PRIMARY]

    note:当然可以使用 alt+f1实现

  • 相关阅读:
    18 | 为什么这些SQL语句逻辑相同,性能却差异巨大?
    17 | 如何正确地显示随机消息?
    16 | “order by”是怎么工作的?
    15 | 答疑文章(一):日志和索引相关问题
    14 | count(*)这么慢,我该怎么办?
    13 | 为什么表数据删掉一半,表文件大小不变?
    12 | 为什么我的MySQL会“抖”一下?
    11 | 怎么给字符串字段加索引?
    10 | MySQL为什么有时候会选错索引?
    2016 Multi-University Training Contest 4
  • 原文地址:https://www.cnblogs.com/llgg/p/5781089.html
Copyright © 2011-2022 走看看