【发布时间】:2020-11-11 20:16:41
【问题描述】:
我正在尝试使用 while 循环 ALTER 索引。
以下代码获取所有大于 30% 分片的 INDEX STATEMENTS。存储到 TEMP 表中。
我正在尝试使用 while 循环进行迭代并执行每个 ALTER STATEMENT。
注意:我不想使用光标。
WITH resultset AS
(
SELECT
DB_NAME() AS 'DB Name',
dbtables.[name] AS 'Table Name',
dbindexes.[name] AS 'Index Name',
indexstats.avg_fragmentation_in_percent as '% Fragmented',
indexstats.page_count as 'Page Count',
'Query' = case when avg_fragmentation_in_percent between 10 and 29.99 then 'ALTER INDEX '+dbindexes.[name] +' ON '+dbtables.[name]+' REBUILD'
when avg_fragmentation_in_percent >= 30 then 'ALTER INDEX '+dbindexes.[name] +' ON '+dbtables.[name]+' REBUILD' end
FROM
sys.DM_DB_INDEX_PHYSICAL_STATS(DB_ID(), NULL, NULL, NULL, NULL) AS indexstats
INNER JOIN
sys.tables dbtables ON dbtables.[object_id] = indexstats.[object_id]
INNER JOIN
sys.schemas dbschemas ON dbtables.[schema_id] = dbschemas.[schema_id]
INNER JOIN
sys.indexes AS dbindexes ON dbindexes.[object_id] = indexstats.[object_id]
AND indexstats.index_id = dbindexes.index_id
WHERE
dbindexes.name IS NOT NULL
AND dbtables.Temporal_type <> 1
AND indexstats.avg_fragmentation_in_percent >= 30
)
SELECT *
INTO #FragmentationTable
FROM resultset
DECLARE @ROWCOUNT INT
DECLARE @execute nvarchar(500)
SELECT @ROWCOUNT= COUNT(1) FROM #FragmentationTable
SELECT @ROWCOUNT
DECLARE @cnt INT = 0 ;
WHILE @cnt < @ROWCOUNT
BEGIN
select @execute=query from #FragmentationTable
--EXEC sp_executesql @execute
print @execute
SET @cnt = @cnt + 1;
END;
PRINT 'THIS IS OUTSIDE OF THE LOOP'
DROP TABLE #FragmentationTable
输出是这样的。它只改变一个索引。
【问题讨论】:
-
您为什么希望
select @execute=query from #FragmentationTable每次都返回不同的行?您必须以某种方式告诉 SQL Server 您已经处理了“第一”行,以便它移动到第二行(您需要一个行号来识别 next 行,或删除您刚刚处理的行)。或者,与其构建 80 个命令并将它们填充到一个表中,一次执行一个,为什么不构建一组 80 个命令并执行一次呢? -
提示:将对象名称组装成动态 SQL 语句的最佳实践是使用
QuoteName()以避免出现奇怪名称的问题,例如New Table带有空格或保留字,例如From。
标签: sql-server azure tsql indexing