Problem
One of the main functions of a DBA is to maintain indexes. There have been several tips written about different commands to use for index rebuilds and index reorgs, as well as the differences between index maintenance with SQL Server. In addition, other tips have been written about using maintenance plans to maintain indexes on all databases. One of the issues with maintenance plans is that they don’t always seem to be as reliable as you would hope. You also sometimes get false feedback on whether the task actually was successful or not. In this tip, we look at a simple script that could be used to rebuild all indexes for all databases.
Solution
The one nice thing about maintenance plans is that they work across multiple databases. Therefore, you can push out one task to handle the same activity across all of your databases. The problem that I have seen with maintenance plans is that sometimes they do not work as expected. This tip provides another approach.
The script below allows you to rebuild indexes for all databases and all tables within a database. This could be further tweaked to handle only indexes that need maintenance based on fragmentation levels as well as then doing either an index reorg or an index rebuild.
The script uses two cursors, one for the databases and another for the tables, within the database. These could be easily changed to while loops if you don’t want to use cursors.
Rebuild All Indexes in all Databases Script
The below script will rebuild all indexes for all databases for versions SQL Server 2005 through SQL Server 2025.
Because we need to change from database to database, we need to create dynamic SQL code for the queries. The code uses master.sys.databases to get a list of databases, as well as check the status for the database, to make sure we are working with databases that are online. This also uses INFORMATION_SCHEMA.TABLES to get a list of user tables in the database.
DECLARE @Database NVARCHAR(255)
DECLARE @Table NVARCHAR(255)
DECLARE @cmd NVARCHAR(1000)
DECLARE DatabaseCursor CURSOR READ_ONLY FOR
SELECT name FROM master.sys.databases
WHERE name NOT IN ('master','msdb','tempdb','model','distribution') -- databases to exclude
--WHERE name IN ('DB1', 'DB2') -- use this to select specific databases and comment out line above
AND state = 0 -- database is online
AND is_in_standby = 0 -- database is not read only for log shipping
ORDER BY 1
OPEN DatabaseCursor
FETCH NEXT FROM DatabaseCursor INTO @Database
WHILE @@FETCH_STATUS = 0
BEGIN
SET @cmd = 'DECLARE TableCursor CURSOR READ_ONLY FOR SELECT ''['' + table_catalog + ''].['' + table_schema + ''].['' +
table_name + '']'' as tableName FROM [' + @Database + '].INFORMATION_SCHEMA.TABLES WHERE table_type = ''BASE TABLE'''
-- create table cursor
EXEC (@cmd)
OPEN TableCursor
FETCH NEXT FROM TableCursor INTO @Table
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
SET @cmd = 'ALTER INDEX ALL ON ' + @Table + ' REBUILD'
--PRINT @cmd -- uncomment if you want to see commands
EXEC (@cmd)
END TRY
BEGIN CATCH
PRINT '---'
PRINT @cmd
PRINT ERROR_MESSAGE()
PRINT '---'
END CATCH
FETCH NEXT FROM TableCursor INTO @Table
END
CLOSE TableCursor
DEALLOCATE TableCursor
FETCH NEXT FROM DatabaseCursor INTO @Database
END
CLOSE DatabaseCursor
DEALLOCATE DatabaseCursorNotes
I have excluded the system databases. You can include these or add other databases to exclude from your index maintenance routines. Also, you can change the code to include only specific databases.
This script has been tested and will work with SQL Server 2005, SQL Server 2008, SQL Server 2008R2, SQL Server 2012, SQL Server 2014, SQL Server 2016, SQL Server 2017, SQL Server 2019, SQL Server 2022, and SQL Server 2025.
Next Steps
- This is a simple base script that could be modified into a stored procedure and also allow you to pass other parameters such as doing an index rebuild or an index defrag.
- Make the index rebuild statements more robust with other options.
- You could also modify this to read from a table that you create to identify which databases and which indexes you want to run this against. You can look at index fragmentation and only rebuild the indexes that need to be rebuilt.
- This approach rebuilds all indexes, so be careful if you run this on very large indexes or large databases because it will take some time to complete and consume memory, cpu and disk resources.
- Take a look at these other index related tips

Greg Robidoux has been working with databases for 35+ years with extensive hands on SQL Server experience from version 6.5 to 2025. He has authored over 250 technical articles and delivered several presentations online and at various conventions. Greg is also the President and founder of Edgewood Solutions, a technology services company delivering services and solutions for Microsoft SQL Server.
Exec sp_msforeachtable ‘ALTER INDEX ALL ON ? REBUILD’
Hi Jeff, thanks for the input. I agree this is not the ideal situation, but this comes in very handy when you have lots of small databases that you need to update. There are several other articles on the site that show how to be selective when rebuilding indexes.
Thanks
Greg
While I appreciate anyone that steps up to the plate with an article and a script, be real careful folks. Rebuilding ALL indexes is a form of “Death by SQL”.
First, you have a whole lot of indexes that simply don’t need any maintenance. Rebuilding those is a total waste of time and resources and will make your log file much more busy that it needs to be, which also affects how long your log file backups take and how big they are.
Second, if you do have indexes that are fragmenting and you don’t actually know why, then rebuilding them may 1)) be a total waste of time for “append only but expansively updated” types of indexes and 2) if the FILL FACTOR doesn’t actually help OR your FILL FACTOR is still set to 0 (same as 100), then you’ve just removed ALL freespace from the index and you will suffer from massive page splits on the proverbial “morning after” which makes for a huge log file and a whole lot of blocking (while the pages split), and more.
You. Are. Awesome.
Excellent script- worked the very first time.