将存储过程的值插入物理表

时间:2016-05-26 06:23:19

标签: sql-server stored-procedures

我需要将以下存储过程的输出插入物理表。

我试过了

CREATE TABLE PARTITION_TABLE_STATUS
( 
    index_action varchar(10),
    object_name varchar(100)
    ,index_name varchar(500)
    ,type_desc varchar(100)
    ,indexed_columns varchar(500)
    ,included_columns varchar(50)
    ,ddl_drop varchar(500)
    ,ddl_create varchar(500)
)

INSERT INTO PARTITION_TABLE_STATUS
     EXEC SP_INDEXANALYSIS2005

但我收到了错误

  

无法嵌套INSERT EXEC语句。

下面是需要执行的存储过程,并将值插入到物理表中:

CREATE PROCEDURE sp_IndexAnalysis2005
    (@ObjectName sysname = NULL)
AS
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    SET NOCOUNT ON

    DECLARE @SQL nvarchar(max), 
            @DB_ID int, 
            @ObjectID int,
            @DatabaseName nvarchar(max),
            @DefaultFillFactor tinyint,
            @DefaultFileGroup nvarchar(max)

    BEGIN TRY
        SELECT 
            @DB_ID = DB_ID(),
            @ObjectID = OBJECT_ID(DB_NAME(DB_ID()) + '.' + @ObjectName),
            @DatabaseName = QUOTENAME(DB_NAME(DB_ID()))

        -- Obtain Default Fill Factor
        SET @SQL = 'SELECT @DefaultFillFactor = CAST(value AS tinyint) '
        + 'FROM '+@DatabaseName+'.sys.configurations WHERE configuration_id = 109'

        EXEC sp_ExecuteSQL @SQL, N'@DefaultFillFactor tinyint OUTPUT', @DefaultFillFactor = @DefaultFillFactor OUTPUT

        -- Obtain Default File Group
        SET @SQL = 'SELECT @DefaultFileGroup = name '
        + 'FROM '+@DatabaseName+'.sys.data_spaces WHERE is_default = 1'

        EXEC sp_ExecuteSQL @SQL, N'@DefaultFileGroup sysname OUTPUT', @DefaultFileGroup = @DefaultFileGroup OUTPUT

        -- Obtain memory buffer information on database objects
        IF OBJECT_ID('tempdb..#MemoryBuffer') IS NOT NULL
            DROP TABLE #MemoryBuffer

        CREATE TABLE #MemoryBuffer 
        (
            object_id int,
            index_id int,
            partition_number int,
            buffered_page_count int,
            buffer_mb decimal(12, 2)
        )

        SET @SQL = 'WITH AllocationUnits
        AS (
        SELECT p.object_id
            ,p.index_id
            ,p.partition_number 
            ,au.allocation_unit_id
        FROM '+@DatabaseName+'.sys.allocation_units AS au
            INNER JOIN '+@DatabaseName+'.sys.partitions AS p ON au.container_id = p.hobt_id AND (au.type = 1 OR au.type = 3)
        UNION ALL
        SELECT p.object_id
            ,p.index_id
            ,p.partition_number 
            ,au.allocation_unit_id
        FROM '+@DatabaseName+'.sys.allocation_units AS au
            INNER JOIN '+@DatabaseName+'.sys.partitions AS p ON au.container_id = p.partition_id AND au.type = 2
    )
    SELECT au.object_id
        ,au.index_id
        ,au.partition_number
        ,COUNT(*)AS buffered_page_count
        ,CONVERT(decimal(12,2), CAST(COUNT(*) as bigint)*CAST(8 as float)/1024) as buffer_mb
    FROM '+@DatabaseName+'.sys.dm_os_buffer_descriptors AS bd 
        INNER JOIN AllocationUnits au ON bd.allocation_unit_id = au.allocation_unit_id
    WHERE bd.database_id = db_id()
    GROUP BY au.object_id, au.index_id, au.partition_number'

    INSERT INTO #MemoryBuffer
    EXEC sp_ExecuteSQL @SQL

    -- Create Main Temporary Tables
    IF OBJECT_ID('tempdb..#IndexBaseLine') IS NOT NULL
        DROP TABLE #IndexBaseLine

    CREATE TABLE #IndexBaseLine
        (
        row_id int IDENTITY(1,1)
        ,index_action varchar(10)
        ,pros varchar(25)
        ,cons varchar(25)
        ,filegroup nvarchar(128)
        ,schema_id int
        ,schema_name sysname
        ,object_id int
        ,table_name sysname
        ,index_id int
        ,index_name nvarchar(128)
        ,is_primary_key bit DEFAULT(0)
        ,is_unique bit DEFAULT(0)
        ,has_unique bit DEFAULT(0)
        ,type_desc nvarchar(67)
        ,partition_number int
        ,fill_factor tinyint
        ,is_padded bit
        ,reserved_page_count bigint
        ,size_in_mb decimal(12, 2)
        ,buffered_page_count int
        ,buffer_mb decimal(12, 2)
        ,pct_in_buffer decimal(12, 2)
        ,table_buffer_mb decimal(12, 2)
        ,row_count bigint
        ,impact int
        ,existing_ranking bigint
        ,user_total bigint
        ,user_total_pct decimal(6, 2)
        ,estimated_user_total_pct decimal(6, 2)
        ,user_seeks bigint
        ,user_scans bigint
        ,user_lookups bigint
        ,user_updates bigint
        ,read_to_update_ratio nvarchar(30)
        ,read_to_update int
        ,update_to_read int
        ,row_lock_count bigint
        ,row_lock_wait_count bigint
        ,row_lock_wait_in_ms bigint
        ,row_block_pct decimal(6, 2)
        ,avg_row_lock_waits_ms bigint
        ,page_latch_wait_count bigint
        ,avg_page_latch_wait_ms bigint
        ,page_io_latch_wait_count bigint
        ,avg_page_io_latch_wait_ms bigint
        ,tree_page_latch_wait_count bigint
        ,avg_tree_page_latch_wait_ms bigint
        ,tree_page_io_latch_wait_count bigint
        ,avg_tree_page_io_latch_wait_ms bigint    
        ,read_operations bigint
        ,leaf_writes bigint
        ,leaf_page_allocations bigint    
        ,leaf_page_merges bigint    
        ,nonleaf_writes bigint
        ,nonleaf_page_allocations bigint
        ,nonleaf_page_merges bigint    
        ,indexed_columns nvarchar(max)
        ,included_columns nvarchar(max)
        ,indexed_columns_compare nvarchar(max)
        ,included_columns_compare nvarchar(max)
        ,duplicate_indexes nvarchar(max)
        ,overlapping_indexes nvarchar(max)
        ,related_foreign_keys nvarchar(max)
        ,related_foreign_keys_xml xml
        )

     -- Populate stats on existing indexes.
     SET @SQL = N'SELECT 
        filegroup = ds.name
        , schema_id =  s.schema_id
        , schema_name = s.name
        , object_id = t.object_id
        , table_name = t.name
        , index_id = i.index_id
        , index_name = COALESCE(i.name, ''N/A'')
        , is_primary_key = i.is_primary_key
        , is_unique = i.is_unique
        , type_desc = CASE WHEN i.is_unique = 1 THEN ''UNIQUE '' ELSE '''' END + i.type_desc
        , partition_number = ps.partition_number
        , fill_factor = i.fill_factor
        , is_padded = i.is_padded
        , reserved_page_count = ps.reserved_page_count
        , size_in_mb = CAST(reserved_page_count * CAST(8 as float) / 1024 as decimal(12,2)) 
        , buffered_page_count = mb.buffered_page_count
        , buffer_mb = mb.buffer_mb
        , pct_in_buffer = CAST(100*buffer_mb/NULLIF(CAST(reserved_page_count * CAST(8 as float) / 1024 as decimal(12,2)),0) AS decimal(12,2)) 
        , row_count = row_count
        , existing_ranking = ROW_NUMBER() 
            OVER (PARTITION BY i.object_id ORDER BY i.is_primary_key desc, ius.user_seeks + ius.user_scans + ius.user_lookups desc) 
        , user_total = ius.user_seeks + ius.user_scans + ius.user_lookups
        , user_total_pct = COALESCE(CAST(100 * (ius.user_seeks + ius.user_scans + ius.user_lookups)
            /(NULLIF(SUM(ius.user_seeks + ius.user_scans + ius.user_lookups) 
            OVER(PARTITION BY i.object_id), 0) * 1.) as decimal(6,2)),0)
        , user_seeks = ius.user_seeks
        , user_scans = ius.user_scans
        , user_lookups = ius.user_lookups
        , user_updates = ius.user_updates
        , read_to_update_ratio = (1.*(ius.user_seeks + ius.user_scans + ius.user_lookups))/NULLIF(ius.user_updates,0)
        , read_to_update = CASE WHEN ius.user_seeks + ius.user_scans + ius.user_lookups >= ius.user_updates
            THEN CEILING(1.*(ius.user_seeks + ius.user_scans + ius.user_lookups)/COALESCE(NULLIF(ius.user_seeks,0),1)) 
            ELSE 0 END 
        , update_to_read = CASE WHEN ius.user_seeks + ius.user_scans + ius.user_lookups <= ius.user_updates
            THEN CEILING(1.*(ius.user_updates)/COALESCE(NULLIF(ius.user_seeks + ius.user_scans + ius.user_lookups,0),1)) 
            ELSE 0 END
        , row_lock_count = ios.row_lock_count
        , row_lock_wait_count = ios.row_lock_wait_count
        , row_lock_wait_in_ms = ios.row_lock_wait_in_ms
        , row_block_pct = CAST(100.0 * ios.row_lock_wait_count/NULLIF(ios.row_lock_count, 0) AS decimal(12,2)) 
        , avg_row_lock_waits_ms = CAST(1. * ios.row_lock_wait_in_ms /NULLIF(ios.row_lock_wait_count, 0) AS decimal(12,2))
        , page_latch_wait_count = ios.page_latch_wait_count
        , avg_page_latch_wait_ms = CAST(1. * page_latch_wait_in_ms / NULLIF(ios.page_io_latch_wait_count,0) AS decimal(12,2)) 
        , page_io_latch_wait_count = ios.page_io_latch_wait_count
        , avg_page_io_latch_wait_ms = CAST(1. * ios.page_io_latch_wait_in_ms / NULLIF(ios.page_io_latch_wait_count,0) AS decimal(12,2))
        , tree_page_latch_wait_count = NULL --ios.tree_page_latch_wait_count
        , avg_tree_page_latch_wait_ms = NULL --CAST(1. * tree_page_latch_wait_in_ms / NULLIF(ios.tree_page_io_latch_wait_count,0) AS decimal(12,2)) 
        , tree_page_io_latch_wait_count = NULL --ios.tree_page_io_latch_wait_count
        , avg_tree_page_io_latch_wait_ms = NULL --CAST(1. * ios.tree_page_io_latch_wait_in_ms / NULLIF(ios.tree_page_io_latch_wait_count,0) AS decimal(12,2)) 
        , read_operations = range_scan_count + singleton_lookup_count
        , leaf_writes = ios.leaf_insert_count + ios.leaf_update_count + ios.leaf_delete_count + ios.leaf_ghost_count
        , leaf_page_allocations = leaf_allocation_count
        , leaf_page_merges = ios.leaf_page_merge_count
        , nonleaf_writes = ios.nonleaf_insert_count + ios.nonleaf_update_count + ios.nonleaf_delete_count
        , nonleaf_page_allocations = ios.nonleaf_allocation_count
        , nonleaf_page_merges = ios.nonleaf_page_merge_count' +
    '    , indexed_columns = STUFF((
                SELECT '', '' + QUOTENAME(c.name)
                FROM '+@DatabaseName+'.sys.index_columns ic
                    INNER JOIN '+@DatabaseName+'.sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
                WHERE i.object_id = ic.object_id
                AND i.index_id = ic.index_id
                AND is_included_column = 0
                ORDER BY key_ordinal ASC
                FOR XML PATH('''')), 1, 2, '''')
        , included_columns = STUFF((
                SELECT '', '' + QUOTENAME(c.name)
                FROM '+@DatabaseName+'.sys.index_columns ic
                    INNER JOIN '+@DatabaseName+'.sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
                WHERE i.object_id = ic.object_id
                AND i.index_id = ic.index_id
                AND is_included_column = 1
                ORDER BY key_ordinal ASC
                FOR XML PATH('''')), 1, 2, '''') 
        , indexed_columns_compare = (SELECT QUOTENAME(ic.column_id,''('')
                FROM '+@DatabaseName+'.sys.index_columns ic
                WHERE i.object_id = ic.object_id
                AND i.index_id = ic.index_id
                AND is_included_column = 0
                ORDER BY key_ordinal ASC
                FOR XML PATH(''''))
        , included_columns_compare = COALESCE((
                SELECT QUOTENAME(ic.column_id, ''('')
                FROM '+@DatabaseName+'.sys.index_columns ic
                WHERE i.object_id = ic.object_id
                AND i.index_id = ic.index_id
                AND is_included_column = 1
                ORDER BY key_ordinal ASC
                FOR XML PATH('''')), SPACE(0)) 
    FROM '+@DatabaseName+'.sys.tables t
        INNER JOIN '+@DatabaseName+'.sys.schemas s ON t.schema_id = s.schema_id
        INNER JOIN '+@DatabaseName+'.sys.indexes i ON t.object_id = i.object_id
        INNER JOIN '+@DatabaseName+'.sys.data_spaces ds ON i.data_space_id = ds.data_space_id
        INNER JOIN '+@DatabaseName+'.sys.dm_db_partition_stats ps ON i.object_id = ps.object_id AND i.index_id = ps.index_id
        LEFT OUTER JOIN sys.dm_db_index_usage_stats ius ON i.object_id = ius.object_id AND i.index_id = ius.index_id AND ius.database_id = db_id()
        LEFT OUTER JOIN sys.dm_db_index_operational_stats(@DB_ID, NULL, NULL, NULL) ios ON ps.object_id = ios.object_id AND ps.index_id = ios.index_id AND ps.partition_number = ios.partition_number
        LEFT OUTER JOIN #MemoryBuffer mb ON ps.object_id = mb.object_id AND ps.index_id = mb.index_id AND ps.partition_number = mb.partition_number'

    IF @ObjectID IS NOT NULL
        SET @SQL = @SQL + CHAR(13) + 'WHERE t.object_id = @ObjectID '

    INSERT INTO #IndexBaseLine
        (
        filegroup, schema_id, schema_name, object_id, table_name, index_id, index_name, is_primary_key, is_unique, type_desc, partition_number, fill_factor
        , is_padded, reserved_page_count, size_in_mb, buffered_page_count, buffer_mb, pct_in_buffer, row_count, existing_ranking, user_total
        , user_total_pct, user_seeks, user_scans, user_lookups, user_updates, read_to_update_ratio, read_to_update, update_to_read, row_lock_count
        , row_lock_wait_count, row_lock_wait_in_ms, row_block_pct, avg_row_lock_waits_ms, page_latch_wait_count, avg_page_latch_wait_ms
        , page_io_latch_wait_count, avg_page_io_latch_wait_ms, tree_page_latch_wait_count, avg_tree_page_latch_wait_ms, tree_page_io_latch_wait_count
        , avg_tree_page_io_latch_wait_ms, read_operations, leaf_writes, leaf_page_allocations, leaf_page_merges, nonleaf_writes
        , nonleaf_page_allocations, nonleaf_page_merges, indexed_columns, included_columns, indexed_columns_compare, included_columns_compare
        )   
    EXEC sp_ExecuteSQL @SQL, N'@DB_ID int, @ObjectID int', @DB_ID = @DB_ID, @ObjectID = @ObjectID

    -- Populate stats on missing indexes.
     SET @SQL = N'SELECT s.schema_id
        ,s.name AS schema_name
        ,t.object_id
        ,t.name AS table_name
        ,''--MISSING--'' AS index_name
        ,''--NONCLUSTERED--'' AS type_desc
        ,(migs.user_seeks + migs.user_scans) * migs.avg_user_impact as impact
        ,0 AS existing_ranking
        ,migs.user_seeks + migs.user_scans as user_total
        ,migs.user_seeks 
        ,migs.user_scans
        ,0 as user_lookups
        ,COALESCE(equality_columns + CASE WHEN inequality_columns IS NOT NULL THEN '', '' ELSE SPACE(0) END, SPACE(0)) + COALESCE(inequality_columns, SPACE(0)) as indexed_columns
        ,included_columns
    FROM '+@DatabaseName+'.sys.tables t
        INNER JOIN '+@DatabaseName+'.sys.schemas s ON t.schema_id = s.schema_id
        INNER JOIN sys.dm_db_missing_index_details mid ON t.object_id = mid.object_id
        INNER JOIN sys.dm_db_missing_index_groups mig ON mid.index_handle = mig.index_handle
        INNER JOIN sys.dm_db_missing_index_group_stats migs ON mig.index_group_handle = migs.group_handle
    WHERE mid.database_id = @DB_ID'

    IF @ObjectID IS NOT NULL
        SET @SQL = @SQL + CHAR(13) + 'AND t.object_id = @ObjectID '

    INSERT INTO #IndexBaseLine
        (schema_id, schema_name, object_id, table_name, index_name, type_desc, impact, existing_ranking, user_total, user_seeks, user_scans, user_lookups, indexed_columns, included_columns)
    EXEC sp_ExecuteSQL @SQL, N'@DB_ID int, @ObjectID int', @DB_ID = @DB_ID, @ObjectID = @ObjectID

    -- Collect foreign key information.
    IF OBJECT_ID('tempdb..#ForeignKeys') IS NOT NULL
        DROP TABLE #ForeignKeys

    CREATE TABLE #ForeignKeys
        (
        foreign_key_name sysname
        ,object_id int
        ,fk_columns nvarchar(max)
        ,fk_columns_compare nvarchar(max)
        )

     SET @SQL = N'SELECT fk.name + ''|PARENT'' AS foreign_key_name
        ,fkc.parent_object_id AS object_id
        ,STUFF((SELECT '', '' + QUOTENAME(c.name)
            FROM '+@DatabaseName+'.sys.foreign_key_columns ifkc
                INNER JOIN '+@DatabaseName+'.sys.columns c ON ifkc.parent_object_id = c.object_id AND ifkc.parent_column_id = c.column_id
            WHERE fk.object_id = ifkc.constraint_object_id
            ORDER BY ifkc.constraint_column_id
            FOR XML PATH('''')), 1, 2, '''') AS fk_columns
        ,(SELECT QUOTENAME(ifkc.parent_column_id,''('')
            FROM '+@DatabaseName+'.sys.foreign_key_columns ifkc
            WHERE fk.object_id = ifkc.constraint_object_id
            ORDER BY ifkc.constraint_column_id
            FOR XML PATH('''')) AS fk_columns_compare
    FROM '+@DatabaseName+'.sys.foreign_keys fk
        INNER JOIN '+@DatabaseName+'.sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id
    WHERE fkc.constraint_column_id = 1
    AND (fkc.parent_object_id = @ObjectID OR @ObjectID IS NULL)
    UNION ALL
    SELECT fk.name + ''|REFERENCED'' as foreign_key_name
        ,fkc.referenced_object_id AS object_id
        ,STUFF((SELECT '', '' + QUOTENAME(c.name)
            FROM '+@DatabaseName+'.sys.foreign_key_columns ifkc
                INNER JOIN '+@DatabaseName+'.sys.columns c ON ifkc.referenced_object_id = c.object_id AND ifkc.referenced_column_id = c.column_id
            WHERE fk.object_id = ifkc.constraint_object_id
            ORDER BY ifkc.constraint_column_id
            FOR XML PATH('''')), 1, 2, '''') AS fk_columns
        ,(SELECT QUOTENAME(ifkc.referenced_column_id,''('')
            FROM '+@DatabaseName+'.sys.foreign_key_columns ifkc
            WHERE fk.object_id = ifkc.constraint_object_id
            ORDER BY ifkc.constraint_column_id
            FOR XML PATH('''')) AS fk_columns_compare
    FROM '+@DatabaseName+'.sys.foreign_keys fk
        INNER JOIN '+@DatabaseName+'.sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id
    WHERE fkc.constraint_column_id = 1
    AND (fkc.referenced_object_id = @ObjectID OR @ObjectID IS NULL)'

    INSERT INTO #ForeignKeys
        (foreign_key_name, object_id, fk_columns, fk_columns_compare)
    EXEC sp_ExecuteSQL @SQL, N'@DB_ID int, @ObjectID int', @DB_ID = @DB_ID, @ObjectID = @ObjectID

    -- Determine duplicate, overlapping, and foreign key index information
    UPDATE ibl
    SET duplicate_indexes = STUFF((SELECT ', ' + index_name AS [data()]
            FROM #IndexBaseLine iibl
            WHERE ibl.object_id = iibl.object_id
            AND ibl.index_id > iibl.index_id
            AND ibl.indexed_columns_compare = iibl.indexed_columns_compare
            AND ibl.included_columns_compare = iibl.included_columns_compare
            FOR XML PATH('')), 1, 2, '')
        ,overlapping_indexes = STUFF((SELECT ', ' + index_name AS [data()]
            FROM #IndexBaseLine iibl
            WHERE ibl.object_id = iibl.object_id
            AND ibl.index_id <> iibl.index_id
            AND (ibl.indexed_columns_compare LIKE iibl.indexed_columns_compare + '%' 
                OR iibl.indexed_columns_compare LIKE ibl.indexed_columns_compare + '%')
            AND ibl.indexed_columns_compare <> iibl.indexed_columns_compare 
            FOR XML PATH('')), 1, 2, '')
        ,related_foreign_keys = STUFF((SELECT ', ' + foreign_key_name AS [data()]
            FROM #ForeignKeys ifk
            WHERE ifk.object_id = ibl.object_id
            AND ibl.indexed_columns_compare LIKE ifk.fk_columns_compare + '%'
            FOR XML PATH('')), 1, 2, '')
        ,related_foreign_keys_xml = CAST((SELECT foreign_key_name
            FROM #ForeignKeys ForeignKeys
            WHERE ForeignKeys.object_id = ibl.object_id
            AND ibl.indexed_columns_compare LIKE ForeignKeys.fk_columns_compare + '%'
            FOR XML AUTO) as xml)  
    FROM #IndexBaseLine ibl


     -- Populate stats on missing foreign key indexes
    SET @SQL = N'SELECT s.schema_id
        ,s.name AS schema_name
        ,t.object_id
        ,t.name AS table_name
        ,fk.foreign_key_name AS index_name
        ,''--MISSING FOREIGN KEY--'' as type_desc
        ,9999
        ,fk.fk_columns
        ,t.name AS related_foreign_keys
    FROM '+@DatabaseName+'.sys.tables t
        INNER JOIN '+@DatabaseName+'.sys.schemas s ON t.schema_id = s.schema_id
        INNER JOIN #ForeignKeys fk ON t.object_id = fk.object_id
        LEFT OUTER JOIN #IndexBaseLine ia ON fk.object_id = ia.object_id AND ia.indexed_columns_compare LIKE fk.fk_columns_compare + ''%''
    WHERE ia.index_name IS NULL'

    INSERT INTO #IndexBaseLine
        (schema_id, schema_name, object_id, table_name, index_name, type_desc, existing_ranking, indexed_columns, related_foreign_keys)
    EXEC sp_ExecuteSQL @SQL, N'@DB_ID int, @ObjectID int', @DB_ID = @DB_ID, @ObjectID = @ObjectID

    -- Determine whether tables have unique indexes
    SET @SQL = N'UPDATE ibl
    SET has_unique = 1
    FROM #IndexBaseLine ibl
        INNER JOIN (SELECT DISTINCT object_id FROM '+@DatabaseName+'.sys.indexes i WHERE i.is_unique = 1) x ON ibl.object_id = x.object_id'

    EXEC sp_ExecuteSQL @SQL

    -- Calculate estimated user total for each index.
    ;WITH Aggregation
    AS (
        SELECT row_id
            ,CAST(100. * (user_seeks + user_scans + user_lookups)
                /(NULLIF(SUM(user_seeks + user_scans + user_lookups) 
                OVER(PARTITION BY schema_name, table_name), 0) * 1.) as decimal(12,2)) AS estimated_user_total_pct
            ,SUM(buffer_mb) OVER(PARTITION BY schema_name, table_name) as table_buffer_mb
        FROM #IndexBaseLine 
    )
    UPDATE ibl
    SET estimated_user_total_pct = COALESCE(a.estimated_user_total_pct, 0)
        ,table_buffer_mb = a.table_buffer_mb
    FROM #IndexBaseLine ibl
        INNER JOIN Aggregation a ON ibl.row_id = a.row_id

    -- Update Index Action information
    ;WITH IndexAction
    AS (
        SELECT row_id
            ,CASE WHEN user_lookups > user_seeks AND type_desc IN ('CLUSTERED', 'HEAP', 'UNIQUE CLUSTERED') THEN 'REALIGN'
                WHEN duplicate_indexes IS NOT NULL THEN 'DROP' 
                WHEN type_desc = '--MISSING FOREIGN KEY--' THEN 'CREATE'
                WHEN type_desc = 'XML' THEN '---'
                WHEN is_unique = 1 THEN '---'
                WHEN related_foreign_keys IS NOT NULL THEN '---'
                WHEN type_desc = '--NONCLUSTERED--' AND ROW_NUMBER() OVER (PARTITION BY table_name ORDER BY user_total desc) <= 10 AND estimated_user_total_pct > 1 THEN 'CREATE'
                WHEN type_desc = '--NONCLUSTERED--' THEN 'BLEND'
                WHEN ROW_NUMBER() OVER (PARTITION BY table_name ORDER BY user_total desc, existing_ranking) > 10 THEN 'DROP' 
                WHEN user_total = 0 THEN 'DROP' 
                ELSE '---' END AS index_action
        FROM #IndexBaseLine
    )
    UPDATE ibl
    SET index_action = ia.index_action
    FROM #IndexBaseLine ibl INNER JOIN IndexAction ia
    ON ibl.row_id = ia.row_id

    -- Update Pro/Con statuses
    UPDATE #IndexBaseLine
    SET Pros = COALESCE(STUFF(CASE WHEN related_foreign_keys IS NOT NULL THEN ', FK' ELSE '' END
            + CASE WHEN is_unique = 1 THEN ', UQ' ELSE '' END
            + COALESCE(', ' + CASE WHEN read_to_update BETWEEN 1 AND 9 THEN '$'
                WHEN read_to_update BETWEEN 10 AND 99 THEN '$$'
                WHEN read_to_update BETWEEN 100 AND 999 THEN '$$$'
                WHEN read_to_update > 999 THEN '$$$+' END, '')
            ,1,2,''),'')
        ,Cons = COALESCE(STUFF(CASE WHEN user_seeks / NULLIF(user_scans,0) < 1000 THEN ', SCN' ELSE '' END
            + CASE WHEN duplicate_indexes IS NOT NULL THEN ', DP' ELSE '' END
            + CASE WHEN overlapping_indexes IS NOT NULL THEN ', OV' ELSE '' END
            + COALESCE(', ' + CASE WHEN update_to_read BETWEEN 1 AND 9 THEN '$'
                WHEN update_to_read BETWEEN 10 AND 99 THEN '$$'
                WHEN update_to_read BETWEEN 100 AND 999 THEN '$$$'
                WHEN update_to_read > 999 THEN '$$$+' END, '')
            ,1,2,''),'')

    --Final Output

    SELECT
        index_action
       -- , pros
       -- , cons
        , QUOTENAME(schema_name) + '.' + QUOTENAME(table_name) as object_name
        , index_name
        , type_desc
        , indexed_columns
        , included_columns
        --, is_primary_key
        --, is_unique
        --, has_unique
        --, partition_number
        --, fill_factor
        --, is_padded
        --, size_in_mb
        --, buffer_mb
        --, table_buffer_mb
        --, pct_in_buffer
        --, row_count
        --, user_total_pct
        --, estimated_user_total_pct
        --, impact
        --, user_total
        --, user_seeks
        --, user_scans
        --, user_lookups
        --, user_updates
        --, read_to_update_ratio
        --, read_to_update
        --, update_to_read
        --, row_lock_count
        --, row_lock_wait_count
        --, row_lock_wait_in_ms
        --, row_block_pct
        --, avg_row_lock_waits_ms
        --, page_latch_wait_count
        --, avg_page_latch_wait_ms
        --, page_io_latch_wait_count
        --, avg_page_io_latch_wait_ms
        --, tree_page_latch_wait_count
        --, avg_tree_page_latch_wait_ms
        --, tree_page_io_latch_wait_count
        --, avg_tree_page_io_latch_wait_ms
        --, read_operations
        --, leaf_writes
        --, leaf_page_allocations
        --, leaf_page_merges
        --, nonleaf_writes
        --, nonleaf_page_allocations
        --, nonleaf_page_merges
        --, duplicate_indexes
        --, overlapping_indexes
        --, related_foreign_keys
        --, related_foreign_keys_xml
        ,CAST('<?query --' + CHAR(13)
            + CASE WHEN is_primary_key = 1 OR is_unique = 1 THEN  '-- !! WARNING !! Drop statement will fail if there are dependent objects.' + CHAR(13) + CHAR(13) ELSE SPACE(0) END
            + CASE WHEN index_id = 0 THEN NULL
                WHEN is_primary_key = 1 THEN
                    'IF  EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N''' + QUOTENAME(schema_name) + '.' + QUOTENAME(table_name) + ''') AND name = N''' + index_name + ''')' + CHAR(13)
                    + '    ALTER TABLE '+QUOTENAME(schema_name) + '.' + QUOTENAME(table_name)+' DROP CONSTRAINT ' + QUOTENAME(index_name) + CHAR(13)
                ELSE 
                    'IF  EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N''' + QUOTENAME(schema_name) + '.' + QUOTENAME(table_name) + ''') AND name = N''' 
                    + CASE WHEN index_id IS NULL THEN '<index_name, sysname, ind_test>' ELSE index_name END + ''')' + CHAR(13)
                    + '    DROP INDEX ' + CASE WHEN index_id IS NULL THEN '<index_name, sysname, ind_test>' ELSE index_name END 
                    + ' ON ' + QUOTENAME(schema_name) + '.' + QUOTENAME(table_name) + CHAR(13)
                END
            + CHAR(13) + '--?>' AS xml) as ddl_drop
       ,CAST('<?query --' + CHAR(13)
            + CASE WHEN index_id = 0 THEN NULL
                WHEN is_primary_key = 1 THEN
                    'ALTER TABLE '+QUOTENAME(schema_name) + '.' + QUOTENAME(table_name)+' ADD  CONSTRAINT ' + QUOTENAME(index_name) + ' PRIMARY KEY ' 
                    + CASE WHEN index_id = 1 THEN 'CLUSTERED ' ELSE 'NONCLUSTERED ' END + CHAR(13)
                    + '     ('+indexed_columns+')' + CHAR(13)
                    + CASE WHEN included_columns IS NOT NULL THEN ' INCLUDE ('+included_columns+')' ELSE '' END
                ELSE 'CREATE ' 
                    + CASE WHEN is_unique = 1 THEN 'UNIQUE ' ELSE '' END
                    + CASE WHEN index_id = 1 THEN 'CLUSTERED ' ELSE 'NONCLUSTERED ' END 
                    + 'INDEX ' + CASE WHEN index_id IS NULL THEN '<index_name, sysname, ind_test>' ELSE index_name END
                    + ' ON ' + QUOTENAME(schema_name) + '.' + QUOTENAME(table_name) + CHAR(13)
                    + '     ('+indexed_columns+')' + CHAR(13)
                    + CASE WHEN included_columns IS NOT NULL THEN ' INCLUDE ('+included_columns+')' ELSE '' END
                END
            + ' WITH (PAD_INDEX  = ' + CASE WHEN is_padded = 1 THEN 'ON' ELSE 'OFF' END
            + ', STATISTICS_NORECOMPUTE  = OFF'
            + ', SORT_IN_TEMPDB = OFF'
            + ', IGNORE_DUP_KEY = OFF'
            + ', ONLINE = OFF'
            + ', ALLOW_ROW_LOCKS  = ON'
            + ', ALLOW_PAGE_LOCKS  = ON'
            + ', FILLFACTOR = ' 
            + CONVERT(varchar(3), CASE WHEN COALESCE(fill_factor, @DefaultFillFactor) = 0 THEN 100 ELSE COALESCE(fill_factor, @DefaultFillFactor) END)       
            + ') ON ' + QUOTENAME(COALESCE(filegroup, @DefaultFileGroup))
            + CHAR(13) + '--?>' AS xml) as ddl_create
    FROM #IndexBaseLine
    WHERE (estimated_user_total_pct > 0.01 AND index_id IS NULL)
    OR related_foreign_keys IS NOT NULL
    OR index_id IS NOT NULL
    ORDER BY table_buffer_mb DESC, object_id, user_total DESC

END TRY
BEGIN CATCH
    DECLARE @ERROR_MESSAGE nvarchar(2048)
        ,@ERROR_SEVERITY int
        ,@ERROR_STATE INT

    SELECT @ERROR_MESSAGE  = ERROR_MESSAGE()
        ,@ERROR_SEVERITY = ERROR_SEVERITY()
        ,@ERROR_STATE = ERROR_STATE()

    RAISERROR(@ERROR_MESSAGE, @ERROR_SEVERITY, @ERROR_STATE)
END CATCH

GO

1 个答案:

答案 0 :(得分:0)

你可以避免sp中的所有insert-execs,因为你已经在那里使用了动态sql。

#tables可以从嵌套批次访问。

改写:

INSERT INTO #MemoryBuffer
EXEC sp_ExecuteSQL @SQL

进入这个:

SET @SQL = 'WITH AllocationUnits
AS (
    SELECT p.object_id
        ,p.index_id
        ,p.partition_number 
        ,au.allocation_unit_id
    FROM '+@DatabaseName+'.sys.allocation_units AS au
        INNER JOIN '+@DatabaseName+'.sys.partitions AS p ON au.container_id = p.hobt_id AND (au.type = 1 OR au.type = 3)
    UNION ALL
    SELECT p.object_id
        ,p.index_id
        ,p.partition_number 
        ,au.allocation_unit_id
    FROM '+@DatabaseName+'.sys.allocation_units AS au
        INNER JOIN '+@DatabaseName+'.sys.partitions AS p ON au.container_id = p.partition_id AND au.type = 2
)
/* INSERT HERE */
INSERT INTO #MemoryBuffer(object_id, index_id, ...)
SELECT au.object_id
    ,au.index_id
...
/* just exec without insert */
EXEC sp_ExecuteSQL @SQL

和所有其他insert-exec条目

相关问题