Sql server EXEC sp_executesql @sql、@parmDef、@schemaName=@schemaName、@objectName= @对象名称, @lobData=@lobData输出 结束 柱 如果@indexType='非聚集索引' 开始 SET@sql='1!' 选择@lobData=1 来自'+QUOTENAME(@dbName)+'.sys.i 连接'+QUOTENAME(@dbName)+'.sys.index_列 在i.object\u id=ic.object\u id上 连接'+QUOTENAME(@dbName)+'。信息'u SCHEMA.c列 在ic.column_id=c.ORDINAL_位置上 其中c.TABLE_SCHEMA=@schemaName和 c、 表_NAME=@objectName和 i、 name=@indexName和 ic.是否包含?列=1和 (c.输入数据(“文本”、“ntext”、“图像”) 或c.字符(最大长度=-1)' 设置@parmDef=N'@schemaName sysname,@objectName sysname, @indexName sysname,@lobData位输出' EXEC sp_executesql @sql、@parmDef、@schemaName=@schemaName、@objectName= @对象名称, @indexName=@indexName,@lobData=@lobData输出 结束 SET@sql='1!' 选择@partitionCount=COUNT(*) 来自'+QUOTENAME(@dbName)+'.sys.partitions 其中[object_id]=@objectId和index_id=@indexId' 设置@parmDef=N'@objectId int、@indexId int、@partitionCount int-OUTPUT' EXEC sp_executesql @sql、@parmDef、@objectId=@objectId、@indexId=@indexId、, @partitionCount=@partitionCount输出 如果@edition=3且(@defragType='REBUILD'或(@defragType= “重新组织”和@allowPageLocks=0) 开始 设置@在线= 案例 当@INDEX键入('XML INDEX','主XML 然后是0 当@indexType='NONCLUSTERED INDEX'和 @allocUnitType=‘LOB_数据’然后为0 当@lobData=1时,则为0 当@disabled=1时,则为0 当@partitionCount>1时,则为0 其他1 结束 结束 其他的 设置@online=0 将@sql='ALTER INDEX'+QUOTENAME(@indexName)+'ON'+ QUOTENAME(@dbName)+'.'+ QUOTENAME(@schemaName)+'.+QUOTENAME(@objectName)+ 案例 当@defragType='Regonize'和@allowPageLocks=0时 “重建” ELSE'+@defragType 结束 如果@online=1或@sortInTempdb=1 开始 将@sql=@sql+'设置为('+ 案例 当@online=1和@sortInTempdb=1时,则为“online”= 打开,在\u TEMPDB=ON'中对\u进行排序 当@online=1和@sortInTempdb=0时,则为“online”= 在 当@online=0且@sortInTempdb=1时 'SORT_IN_TEMPDB=ON' 结束+“)” 结束 如果@partitionCount>1且@disabled=0且@indexType为“XML索引” 设置@sql=@sql+'PARTITION='+CAST(@partitionNumber为 瓦查尔(10)) EXEC(@SQL) 如果@logHistory=1 插入碎片整理索引(DatabaseName、SchemaName、TableName、, IndexName、碎片整理日期、碎片百分比) 值(@dbName、@schemaName、@objectName、@indexName、GETDATE(), @fragPercent) 选择@i=MIN(FragIndexId) 来自#FragIndex FragIndexId>@i在哪里 挑选 @objectId=objectId, @indexId=indexId, @fragPercent=fragPercent, @partitionNumber=partitionNumber, @indexType=indexType, @allocUnitType=allocUnitType 来自#FragIndex 其中FragIndexId=@i 结束 去 EXEC isp\u ALTER\u索引 @dbName='MODEV', @statsMode=‘采样’, @defragType='REBUILD', @minFragPercent=1, @maxFragPercent=100, @minRowCount=10, @logHistory=1, @sortInTempdb=1 去

Sql server EXEC sp_executesql @sql、@parmDef、@schemaName=@schemaName、@objectName= @对象名称, @lobData=@lobData输出 结束 柱 如果@indexType='非聚集索引' 开始 SET@sql='1!' 选择@lobData=1 来自'+QUOTENAME(@dbName)+'.sys.i 连接'+QUOTENAME(@dbName)+'.sys.index_列 在i.object\u id=ic.object\u id上 连接'+QUOTENAME(@dbName)+'。信息'u SCHEMA.c列 在ic.column_id=c.ORDINAL_位置上 其中c.TABLE_SCHEMA=@schemaName和 c、 表_NAME=@objectName和 i、 name=@indexName和 ic.是否包含?列=1和 (c.输入数据(“文本”、“ntext”、“图像”) 或c.字符(最大长度=-1)' 设置@parmDef=N'@schemaName sysname,@objectName sysname, @indexName sysname,@lobData位输出' EXEC sp_executesql @sql、@parmDef、@schemaName=@schemaName、@objectName= @对象名称, @indexName=@indexName,@lobData=@lobData输出 结束 SET@sql='1!' 选择@partitionCount=COUNT(*) 来自'+QUOTENAME(@dbName)+'.sys.partitions 其中[object_id]=@objectId和index_id=@indexId' 设置@parmDef=N'@objectId int、@indexId int、@partitionCount int-OUTPUT' EXEC sp_executesql @sql、@parmDef、@objectId=@objectId、@indexId=@indexId、, @partitionCount=@partitionCount输出 如果@edition=3且(@defragType='REBUILD'或(@defragType= “重新组织”和@allowPageLocks=0) 开始 设置@在线= 案例 当@INDEX键入('XML INDEX','主XML 然后是0 当@indexType='NONCLUSTERED INDEX'和 @allocUnitType=‘LOB_数据’然后为0 当@lobData=1时,则为0 当@disabled=1时,则为0 当@partitionCount>1时,则为0 其他1 结束 结束 其他的 设置@online=0 将@sql='ALTER INDEX'+QUOTENAME(@indexName)+'ON'+ QUOTENAME(@dbName)+'.'+ QUOTENAME(@schemaName)+'.+QUOTENAME(@objectName)+ 案例 当@defragType='Regonize'和@allowPageLocks=0时 “重建” ELSE'+@defragType 结束 如果@online=1或@sortInTempdb=1 开始 将@sql=@sql+'设置为('+ 案例 当@online=1和@sortInTempdb=1时,则为“online”= 打开,在\u TEMPDB=ON'中对\u进行排序 当@online=1和@sortInTempdb=0时,则为“online”= 在 当@online=0且@sortInTempdb=1时 'SORT_IN_TEMPDB=ON' 结束+“)” 结束 如果@partitionCount>1且@disabled=0且@indexType为“XML索引” 设置@sql=@sql+'PARTITION='+CAST(@partitionNumber为 瓦查尔(10)) EXEC(@SQL) 如果@logHistory=1 插入碎片整理索引(DatabaseName、SchemaName、TableName、, IndexName、碎片整理日期、碎片百分比) 值(@dbName、@schemaName、@objectName、@indexName、GETDATE(), @fragPercent) 选择@i=MIN(FragIndexId) 来自#FragIndex FragIndexId>@i在哪里 挑选 @objectId=objectId, @indexId=indexId, @fragPercent=fragPercent, @partitionNumber=partitionNumber, @indexType=indexType, @allocUnitType=allocUnitType 来自#FragIndex 其中FragIndexId=@i 结束 去 EXEC isp\u ALTER\u索引 @dbName='MODEV', @statsMode=‘采样’, @defragType='REBUILD', @minFragPercent=1, @maxFragPercent=100, @minRowCount=10, @logHistory=1, @sortInTempdb=1 去,sql-server,tsql,stored-procedures,Sql Server,Tsql,Stored Procedures,首先。只是糟糕的代码格式!难怪,在这段批量代码中您不会看到任何错误。有一些基本的代码错误。我在下面的声明中修复了它们。其中一个是这样的: EXEC sp_executesql @sql, @parmDef, @schemaName = @schemaName, @objectName = @objectName, @lobData = @lobData OUTPUT END columns -- Why columns? This has no context!

首先。只是糟糕的代码格式!难怪,在这段批量代码中您不会看到任何错误。有一些基本的代码错误。我在下面的声明中修复了它们。其中一个是这样的:

EXEC sp_executesql
    @sql, @parmDef, @schemaName = @schemaName, @objectName =
    @objectName,
    @lobData = @lobData OUTPUT
    END
columns -- Why columns? This has no context!
ELSE ...
请尝试以下方法:

USE master
GO

IF OBJECT_ID('dbo.DefragmentIndexes') IS NULL GOTO CreateTable

DECLARE @ArchiveTableName SYSNAME = 'DefragmentIndexes_Old'

IF EXISTS (SELECT * FROM sys.tables WHERE name = N'DefragmentIndexes_Old')
    DROP TABLE dbo.DefragmentIndexes_Old

EXEC sp_rename N'dbo.DefragmentIndexes', @ArchiveTableName, N'OBJECT';

DECLARE @indexes TABLE (LineID INT NOT NULL IDENTITY(1,1), index_name SYSNAME)

INSERT @indexes
    SELECT i.name
    FROM sys.indexes i
    WHERE i.object_id = OBJECT_ID(@ArchiveTableName)
        AND i.index_id <> 1

DECLARE @i INT, @index_name SYSNAME

SELECT TOP(1) @i = LineId, @index_name = index_name FROM @indexes

WHILE @i IS NOT NULL BEGIN
    EXEC('DROP INDEX ' + @ArchiveTableName + '.' + @index_name)
    DELETE @indexes WHERE LineID = @i
    SET @i = NULL
    SELECT TOP(1) @i = LineId, @index_name = index_name FROM @indexes
END

CreateTable:
CREATE TABLE DefragmentIndexes
(
    LineId INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
    DatabaseName SYSNAME NOT NULL,
    SchemaName SYSNAME NOT NULL,
    TableName SYSNAME NOT NULL,
    IndexName SYSNAME NOT NULL,
    DefragmentDate datetime NOT NULL,
    PercentFragmented decimal(4, 2) NOT NULL,
)
GO
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'nci_DefragmentIndexes_DefragmentDate')
CREATE INDEX nci_DefragmentIndexes_DefragmentDate
    ON DefragmentIndexes (DefragmentDate)
    INCLUDE (SchemaName, TableName)
GO
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name= 'nci_DefragmentIndexes_TableName_SchemaName')
CREATE INDEX nci_DefragmentIndexes_TableName_SchemaName
    ON DefragmentIndexes (TableName, SchemaName)
    INCLUDE (DefragmentDate)


IF OBJECT_ID(N'[dbo].[isp_ALTER_INDEX]') IS NOT NULL
    DROP PROC [dbo].[isp_ALTER_INDEX]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROC [dbo].[isp_ALTER_INDEX]
    @dbName sysname,
    @statsMode varchar(8) = 'SAMPLED',
    @defragType varchar(10) = 'REORGANIZE',
    @minFragPercent int = 25,
    @maxFragPercent int = 100,
    @minRowCount int = 0,
    @logHistory bit = 0,
    @sortInTempdb bit = 0
AS BEGIN
    SET NOCOUNT ON

    IF @statsMode NOT IN ('LIMITED', 'SAMPLED', 'DETAILED') BEGIN
        RAISERROR('@statsMode must be LIMITED, SAMPLED or DETAILED', 16, 1)
        RETURN
    END

    IF @defragType NOT IN ('REORGANIZE', 'REBUILD') BEGIN
        RAISERROR('@defragType must be REORGANIZE or REBUILD', 16, 1)
        RETURN
    END

    DECLARE @i int, @objectId int, @objectName sysname, @indexId int, @indexName sysname,
            @schemaName sysname, @partitionNumber int, @partitionCount int, @sql nvarchar(4000), 
            @edition int, @parmDef nvarchar(500), @allocUnitType nvarchar(60), @indexType nvarchar(60), 
            @online bit, @disabled bit, @dataType nvarchar(128), @charMaxLen int, @allowPageLocks bit, 
            @lobData bit, @fragPercent float

    SELECT @edition = CONVERT(int, SERVERPROPERTY('EngineEdition'))

    SELECT IDENTITY(int, 1, 1) AS FragIndexId,
        [object_id] AS ObjectId,
        index_id AS IndexId,
        avg_fragmentation_in_percent AS FragPercent,
        record_count AS RecordCount,
        partition_number AS PartitionNumber,
        index_type_desc AS IndexType,
        alloc_unit_type_desc AS AllocUnitType
    INTO #FragIndex
    FROM sys.dm_db_index_physical_stats (DB_ID(@dbName), NULL, NULL, NULL, @statsMode)
    WHERE avg_fragmentation_in_percent > @minFragPercent AND
        avg_fragmentation_in_percent < @maxFragPercent AND
        index_id > 0 AND
        index_level = 0
    ORDER BY ObjectId

    IF @statsMode IN ('SAMPLED', 'DETAILED')
        DELETE FROM #FragIndex
        WHERE RecordCount < @minRowCount

    SELECT @i = MIN(FragIndexId)
    FROM #FragIndex

    SELECT @objectId = ObjectId,
        @indexId = IndexId,
        @fragPercent = FragPercent,
        @partitionNumber = PartitionNumber,
        @indexType = IndexType,
        @allocUnitType = AllocUnitType
    FROM #FragIndex
    WHERE FragIndexId = @i

    WHILE @@ROWCOUNT <> 0 BEGIN

        SET @sql = 'SELECT @objectName = o.[name], @schemaName = s.[name]
        FROM ' + QUOTENAME(@dbName) + '.sys.objects o
        JOIN ' + QUOTENAME(@dbName) + '.sys.schemas s
        ON s.schema_id = o.schema_id
        WHERE o.[object_id] = @objectId'

        SET @parmDef = N'@objectId int, @objectName sysname OUTPUT, @schemaName sysname OUTPUT'

        EXEC sp_executesql @sql, @parmDef, @objectId = @objectId, @objectName = @objectName OUTPUT, 
            @schemaName = @schemaName OUTPUT

        SET @sql = 'SELECT @indexName = [name], @disabled = is_disabled, @allowPageLocks = allow_page_locks
            FROM ' + QUOTENAME(@dbName) + '.sys.indexes
            WHERE [object_id] = @objectId AND index_id = @indexId'

        SET @parmDef = N'@objectId int, @indexId int, @indexName sysname OUTPUT, @disabled bit OUTPUT, @allowPageLocks bit OUTPUT'

        EXEC sp_executesql @sql, @parmDef, @objectId = @objectId, @indexId = @indexId, @indexName = @indexName OUTPUT, @disabled = @disabled OUTPUT,
            @allowPageLocks = @allowPageLocks OUTPUT

        SET @lobData = 0

        IF @indexType = 'CLUSTERED INDEX' BEGIN

            SET @sql = '
                SELECT @lobData = 1
                FROM ' + QUOTENAME(@dbName) + '.INFORMATION_SCHEMA.COLUMNS c
                WHERE TABLE_SCHEMA = @schemaName AND
                TABLE_NAME = @objectName AND
                (DATA_TYPE IN (''text'', ''ntext'', ''image'') OR
                CHARACTER_MAXIMUM_LENGTH = -1)'
            SET @parmDef = N'@schemaName sysname, @objectName sysname, @lobData bit OUTPUT'
            EXEC sp_executesql @sql, @parmDef, @schemaName = @schemaName, @objectName = @objectName, 
                @lobData = @lobData OUTPUT
        END
        ELSE IF @indexType = 'NONCLUSTERED INDEX'
        BEGIN
            SET @sql = 'SELECT @lobData = 1
                FROM ' + QUOTENAME(@dbName) + '.sys.indexes i
                JOIN ' + QUOTENAME(@dbName) + '.sys.index_columns ic
                        ON i.object_id = ic.object_id
                JOIN ' + QUOTENAME(@dbName) + '.INFORMATION_SCHEMA.COLUMNS c
                        ON ic.column_id = c.ORDINAL_POSITION
                WHERE c.TABLE_SCHEMA = @schemaName AND
                    c.TABLE_NAME = @objectName AND
                    i.name = @indexName AND
                    ic.is_included_column = 1 AND
                    (c.DATA_TYPE IN (''text'', ''ntext'', ''image'')
                    OR c.CHARACTER_MAXIMUM_LENGTH = -1)'

            SET @parmDef = N'@schemaName sysname, @objectName sysname, @indexName sysname, @lobData bit OUTPUT'

            EXEC sp_executesql @sql, @parmDef, @schemaName = @schemaName, @objectName = @objectName,
                @indexName = @indexName, @lobData = @lobData OUTPUT
        END

        SET @sql = 'SELECT @partitionCount = COUNT(*)
            FROM ' + QUOTENAME(@dbName) + '.sys.partitions
            WHERE [object_id] = @objectId AND index_id = @indexId'

        SET @parmDef = N'@objectId int, @indexId int, @partitionCount int OUTPUT'

        EXEC sp_executesql @sql, @parmDef, @objectId = @objectId, @indexId = @indexId, 
            @partitionCount = @partitionCount OUTPUT

        IF @edition = 3 AND (@defragType = 'REBUILD' OR (@defragType = 'REORGANIZE' AND @allowPageLocks = 0)) BEGIN
            SET @online = CASE  WHEN @indexType IN ('XML INDEX', 'PRIMARY XML INDEX') THEN 0
                                WHEN @indexType = 'NONCLUSTERED INDEX' AND @allocUnitType = 'LOB_DATA' THEN 0
                                WHEN @lobData = 1 THEN 0
                                WHEN @disabled = 1 THEN 0
                                WHEN @partitionCount > 1 THEN 0
                                ELSE 1
                            END
        END
        ELSE
            SET @online = 0

        SET @sql = 'ALTER INDEX ' + QUOTENAME(@indexName) + ' ON ' + QUOTENAME(@dbName) + '.' + 
                    QUOTENAME(@schemaName) + '.' + QUOTENAME(@objectName) +
                    CASE    WHEN @defragType = ' REORGANIZE' AND @allowPageLocks = 0 
                            THEN ' REBUILD'
                            ELSE ' ' + @defragType
                    END

        IF @online = 1 OR @sortInTempdb = 1 BEGIN
            SET @sql = @sql + ' WITH (' +
                    CASE    WHEN @online = 1 AND @sortInTempdb = 1 THEN 'ONLINE = ON, SORT_IN_TEMPDB = ON'
                            WHEN @online = 1 AND @sortInTempdb = 0 THEN 'ONLINE = ON'
                            WHEN @online = 0 AND @sortInTempdb = 1 THEN 'SORT_IN_TEMPDB = ON'
                    END + ')'
        END

        IF @partitionCount > 1 AND @disabled = 0 AND @indexType <> 'XML INDEX'
            SET @sql = @sql + ' PARTITION = ' + CAST(@partitionNumber AS varchar(10))

        EXEC (@SQL)

        IF @logHistory = 1
            INSERT INTO DefragmentIndexes (DatabaseName, SchemaName, TableName, IndexName, DefragmentDate, PercentFragmented)
            VALUES(@dbName, @schemaName, @objectName, @indexName, GETDATE(), @fragPercent)

        SELECT @i = MIN(FragIndexId) 
        FROM #FragIndex 
        WHERE FragIndexId > @i

        SELECT @objectId = ObjectId, @indexId = IndexId, @fragPercent = FragPercent, @partitionNumber = PartitionNumber, 
                @indexType = IndexType, @allocUnitType = AllocUnitType
        FROM #FragIndex
        WHERE FragIndexId = @i
    END
END
GO
EXEC isp_ALTER_INDEX
@dbName = 'MODEV',
@statsMode = 'SAMPLED',
@defragType = 'REBUILD',
@minFragPercent = 1,
@maxFragPercent = 100,
@minRowCount = 10,
@logHistory = 1,
@sortInTempdb = 1
GO
使用master
去
如果对象ID('dbo.DefragmentIndexes')为空,则转到CreateTable
声明@ArchiveTableName SYSNAME='DefragmentIndexes\u Old'
如果存在(从sys.tables中选择*,其中name=N'defragmentindex\u Old')
删除表dbo.defragmentindex\u Old
EXEC sp_rename N'dbo.defragmentindex',@ArchiveTableName,N'OBJECT';
声明@indexes表(LineID INT NOT NULL IDENTITY(1,1),index_name SYSNAME)
插入@index
选择i.name
从sys.i
其中i.object_id=object_id(@ArchiveTableName)
和i.index_id 1
声明@i INT、@index\u name SYSNAME
从@index中选择TOP(1)@i=LineId、@index\u name=index\u name
当@i不为空时,开始
EXEC('DROP INDEX'+@ArchiveTableName+'.+@INDEX_name)
删除LineID=@i的@index
设置@i=NULL
从@index中选择TOP(1)@i=LineId、@index\u name=index\u name
结束
CreateTable:
创建表碎片整理索引
(
LineId INT非空标识(1,1)主键,
DatabaseName SYSNAME不为空,
SchemaName SYSNAME不为NULL,
TableName SYSNAME不为空,
IndexName SYSNAME不为空,
碎片整理日期日期时间不为空,
百分比小数(4,2)不为空,
)
去
如果不存在(从sys.indexes中选择*,其中名称='nci\u碎片整理索引\u碎片整理日期')
创建索引nci\u碎片整理索引\u碎片整理日期
关于碎片整理索引(碎片整理日期)
包括(SchemaName、TableName)
去
如果不存在(从sys.indexes中选择*,其中name='nci\u碎片整理索引\u TableName\u SchemaName')
创建索引nci\u碎片整理索引\u表名\u模式名
关于碎片整理索引(TableName、SchemaName)
包括(碎片整理日期)
如果对象ID(N'[dbo].[isp\U ALTER\U INDEX]'不为空
DROP PROC[dbo].[isp\U ALTER\U INDEX]
去
将ANSI_空值设置为ON
去
在上设置带引号的\u标识符
去
创建进程[dbo]。[isp\u更改\u索引]
@dbName sysname,
@statsMode varchar(8)=‘采样’,
@defragType varchar(10)=“重新组织”,
@minFragPercent int=25,
@maxFragPercent int=100,
@minRowCount int=0,
@日志历史记录位=0,
@sortInTempdb位=0
作为开始
不计较
如果@statsMode不在('LIMITED'、'SAMPLED'、'DETAILED')中,则开始
RAISERROR(“@statsMode必须是有限的、采样的或详细的”,16,1)
返回
结束
如果@defragType不在('REOR
USE master
GO

IF OBJECT_ID('dbo.DefragmentIndexes') IS NULL GOTO CreateTable

DECLARE @ArchiveTableName SYSNAME = 'DefragmentIndexes_Old'

IF EXISTS (SELECT * FROM sys.tables WHERE name = N'DefragmentIndexes_Old')
    DROP TABLE dbo.DefragmentIndexes_Old

EXEC sp_rename N'dbo.DefragmentIndexes', @ArchiveTableName, N'OBJECT';

DECLARE @indexes TABLE (LineID INT NOT NULL IDENTITY(1,1), index_name SYSNAME)

INSERT @indexes
    SELECT i.name
    FROM sys.indexes i
    WHERE i.object_id = OBJECT_ID(@ArchiveTableName)
        AND i.index_id <> 1

DECLARE @i INT, @index_name SYSNAME

SELECT TOP(1) @i = LineId, @index_name = index_name FROM @indexes

WHILE @i IS NOT NULL BEGIN
    EXEC('DROP INDEX ' + @ArchiveTableName + '.' + @index_name)
    DELETE @indexes WHERE LineID = @i
    SET @i = NULL
    SELECT TOP(1) @i = LineId, @index_name = index_name FROM @indexes
END

CreateTable:
CREATE TABLE DefragmentIndexes
(
    LineId INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
    DatabaseName SYSNAME NOT NULL,
    SchemaName SYSNAME NOT NULL,
    TableName SYSNAME NOT NULL,
    IndexName SYSNAME NOT NULL,
    DefragmentDate datetime NOT NULL,
    PercentFragmented decimal(4, 2) NOT NULL,
)
GO
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'nci_DefragmentIndexes_DefragmentDate')
CREATE INDEX nci_DefragmentIndexes_DefragmentDate
    ON DefragmentIndexes (DefragmentDate)
    INCLUDE (SchemaName, TableName)
GO
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name= 'nci_DefragmentIndexes_TableName_SchemaName')
CREATE INDEX nci_DefragmentIndexes_TableName_SchemaName
    ON DefragmentIndexes (TableName, SchemaName)
    INCLUDE (DefragmentDate)


IF OBJECT_ID(N'[dbo].[isp_ALTER_INDEX]') IS NOT NULL
    DROP PROC [dbo].[isp_ALTER_INDEX]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROC [dbo].[isp_ALTER_INDEX]
    @dbName sysname,
    @statsMode varchar(8) = 'SAMPLED',
    @defragType varchar(10) = 'REORGANIZE',
    @minFragPercent int = 25,
    @maxFragPercent int = 100,
    @minRowCount int = 0,
    @logHistory bit = 0,
    @sortInTempdb bit = 0
AS BEGIN
    SET NOCOUNT ON

    IF @statsMode NOT IN ('LIMITED', 'SAMPLED', 'DETAILED') BEGIN
        RAISERROR('@statsMode must be LIMITED, SAMPLED or DETAILED', 16, 1)
        RETURN
    END

    IF @defragType NOT IN ('REORGANIZE', 'REBUILD') BEGIN
        RAISERROR('@defragType must be REORGANIZE or REBUILD', 16, 1)
        RETURN
    END

    DECLARE @i int, @objectId int, @objectName sysname, @indexId int, @indexName sysname,
            @schemaName sysname, @partitionNumber int, @partitionCount int, @sql nvarchar(4000), 
            @edition int, @parmDef nvarchar(500), @allocUnitType nvarchar(60), @indexType nvarchar(60), 
            @online bit, @disabled bit, @dataType nvarchar(128), @charMaxLen int, @allowPageLocks bit, 
            @lobData bit, @fragPercent float

    SELECT @edition = CONVERT(int, SERVERPROPERTY('EngineEdition'))

    SELECT IDENTITY(int, 1, 1) AS FragIndexId,
        [object_id] AS ObjectId,
        index_id AS IndexId,
        avg_fragmentation_in_percent AS FragPercent,
        record_count AS RecordCount,
        partition_number AS PartitionNumber,
        index_type_desc AS IndexType,
        alloc_unit_type_desc AS AllocUnitType
    INTO #FragIndex
    FROM sys.dm_db_index_physical_stats (DB_ID(@dbName), NULL, NULL, NULL, @statsMode)
    WHERE avg_fragmentation_in_percent > @minFragPercent AND
        avg_fragmentation_in_percent < @maxFragPercent AND
        index_id > 0 AND
        index_level = 0
    ORDER BY ObjectId

    IF @statsMode IN ('SAMPLED', 'DETAILED')
        DELETE FROM #FragIndex
        WHERE RecordCount < @minRowCount

    SELECT @i = MIN(FragIndexId)
    FROM #FragIndex

    SELECT @objectId = ObjectId,
        @indexId = IndexId,
        @fragPercent = FragPercent,
        @partitionNumber = PartitionNumber,
        @indexType = IndexType,
        @allocUnitType = AllocUnitType
    FROM #FragIndex
    WHERE FragIndexId = @i

    WHILE @@ROWCOUNT <> 0 BEGIN

        SET @sql = 'SELECT @objectName = o.[name], @schemaName = s.[name]
        FROM ' + QUOTENAME(@dbName) + '.sys.objects o
        JOIN ' + QUOTENAME(@dbName) + '.sys.schemas s
        ON s.schema_id = o.schema_id
        WHERE o.[object_id] = @objectId'

        SET @parmDef = N'@objectId int, @objectName sysname OUTPUT, @schemaName sysname OUTPUT'

        EXEC sp_executesql @sql, @parmDef, @objectId = @objectId, @objectName = @objectName OUTPUT, 
            @schemaName = @schemaName OUTPUT

        SET @sql = 'SELECT @indexName = [name], @disabled = is_disabled, @allowPageLocks = allow_page_locks
            FROM ' + QUOTENAME(@dbName) + '.sys.indexes
            WHERE [object_id] = @objectId AND index_id = @indexId'

        SET @parmDef = N'@objectId int, @indexId int, @indexName sysname OUTPUT, @disabled bit OUTPUT, @allowPageLocks bit OUTPUT'

        EXEC sp_executesql @sql, @parmDef, @objectId = @objectId, @indexId = @indexId, @indexName = @indexName OUTPUT, @disabled = @disabled OUTPUT,
            @allowPageLocks = @allowPageLocks OUTPUT

        SET @lobData = 0

        IF @indexType = 'CLUSTERED INDEX' BEGIN

            SET @sql = '
                SELECT @lobData = 1
                FROM ' + QUOTENAME(@dbName) + '.INFORMATION_SCHEMA.COLUMNS c
                WHERE TABLE_SCHEMA = @schemaName AND
                TABLE_NAME = @objectName AND
                (DATA_TYPE IN (''text'', ''ntext'', ''image'') OR
                CHARACTER_MAXIMUM_LENGTH = -1)'
            SET @parmDef = N'@schemaName sysname, @objectName sysname, @lobData bit OUTPUT'
            EXEC sp_executesql @sql, @parmDef, @schemaName = @schemaName, @objectName = @objectName, 
                @lobData = @lobData OUTPUT
        END
        ELSE IF @indexType = 'NONCLUSTERED INDEX'
        BEGIN
            SET @sql = 'SELECT @lobData = 1
                FROM ' + QUOTENAME(@dbName) + '.sys.indexes i
                JOIN ' + QUOTENAME(@dbName) + '.sys.index_columns ic
                        ON i.object_id = ic.object_id
                JOIN ' + QUOTENAME(@dbName) + '.INFORMATION_SCHEMA.COLUMNS c
                        ON ic.column_id = c.ORDINAL_POSITION
                WHERE c.TABLE_SCHEMA = @schemaName AND
                    c.TABLE_NAME = @objectName AND
                    i.name = @indexName AND
                    ic.is_included_column = 1 AND
                    (c.DATA_TYPE IN (''text'', ''ntext'', ''image'')
                    OR c.CHARACTER_MAXIMUM_LENGTH = -1)'

            SET @parmDef = N'@schemaName sysname, @objectName sysname, @indexName sysname, @lobData bit OUTPUT'

            EXEC sp_executesql @sql, @parmDef, @schemaName = @schemaName, @objectName = @objectName,
                @indexName = @indexName, @lobData = @lobData OUTPUT
        END

        SET @sql = 'SELECT @partitionCount = COUNT(*)
            FROM ' + QUOTENAME(@dbName) + '.sys.partitions
            WHERE [object_id] = @objectId AND index_id = @indexId'

        SET @parmDef = N'@objectId int, @indexId int, @partitionCount int OUTPUT'

        EXEC sp_executesql @sql, @parmDef, @objectId = @objectId, @indexId = @indexId, 
            @partitionCount = @partitionCount OUTPUT

        IF @edition = 3 AND (@defragType = 'REBUILD' OR (@defragType = 'REORGANIZE' AND @allowPageLocks = 0)) BEGIN
            SET @online = CASE  WHEN @indexType IN ('XML INDEX', 'PRIMARY XML INDEX') THEN 0
                                WHEN @indexType = 'NONCLUSTERED INDEX' AND @allocUnitType = 'LOB_DATA' THEN 0
                                WHEN @lobData = 1 THEN 0
                                WHEN @disabled = 1 THEN 0
                                WHEN @partitionCount > 1 THEN 0
                                ELSE 1
                            END
        END
        ELSE
            SET @online = 0

        SET @sql = 'ALTER INDEX ' + QUOTENAME(@indexName) + ' ON ' + QUOTENAME(@dbName) + '.' + 
                    QUOTENAME(@schemaName) + '.' + QUOTENAME(@objectName) +
                    CASE    WHEN @defragType = ' REORGANIZE' AND @allowPageLocks = 0 
                            THEN ' REBUILD'
                            ELSE ' ' + @defragType
                    END

        IF @online = 1 OR @sortInTempdb = 1 BEGIN
            SET @sql = @sql + ' WITH (' +
                    CASE    WHEN @online = 1 AND @sortInTempdb = 1 THEN 'ONLINE = ON, SORT_IN_TEMPDB = ON'
                            WHEN @online = 1 AND @sortInTempdb = 0 THEN 'ONLINE = ON'
                            WHEN @online = 0 AND @sortInTempdb = 1 THEN 'SORT_IN_TEMPDB = ON'
                    END + ')'
        END

        IF @partitionCount > 1 AND @disabled = 0 AND @indexType <> 'XML INDEX'
            SET @sql = @sql + ' PARTITION = ' + CAST(@partitionNumber AS varchar(10))

        EXEC (@SQL)

        IF @logHistory = 1
            INSERT INTO DefragmentIndexes (DatabaseName, SchemaName, TableName, IndexName, DefragmentDate, PercentFragmented)
            VALUES(@dbName, @schemaName, @objectName, @indexName, GETDATE(), @fragPercent)

        SELECT @i = MIN(FragIndexId) 
        FROM #FragIndex 
        WHERE FragIndexId > @i

        SELECT @objectId = ObjectId, @indexId = IndexId, @fragPercent = FragPercent, @partitionNumber = PartitionNumber, 
                @indexType = IndexType, @allocUnitType = AllocUnitType
        FROM #FragIndex
        WHERE FragIndexId = @i
    END
END
GO
EXEC isp_ALTER_INDEX
@dbName = 'MODEV',
@statsMode = 'SAMPLED',
@defragType = 'REBUILD',
@minFragPercent = 1,
@maxFragPercent = 100,
@minRowCount = 10,
@logHistory = 1,
@sortInTempdb = 1
GO