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