Background
I recently wrote an EF Core migration which included dropping an index. This index was somewhat unusual, as it didn’t follow our naming conventions and we didn’t know how it had been added. The disparity in naming suggested it may have been manually added on a database, and might not necessarily be on all databases which are in use across all environments.
Prompted by a very helpful comment in a code review, I wanted to check a number of test databases to see which of them had the index in question. Given the number of databases which needed checking, I wanted to avoid manually checking them all. The obvious solution was to have a SQL script do the work for me.
SQL Script
I asked GitHub Copilot to create a script for me, then modified it myself until I was happy with it. This is the SQL script I used. Although I was happy with how it ran, if you plan to use this then please do check this SQL does what you expect before running it on your own databases.
-- Set these when running the script
DECLARE @SchemaName NVARCHAR(255) = 'TODO'
DECLARE @TableName NVARCHAR(255) = 'TODO'
DECLARE @IndexName NVARCHAR(255) = 'TODO'
-- Leave these for the script to use
DECLARE @DatabaseName NVARCHAR(255)
DECLARE @SQL NVARCHAR(MAX)
-- Create a table to store the results
CREATE TABLE #IndexCheckResults
(
DatabaseName NVARCHAR(255),
IndexExists BIT
)
-- Cursor to iterate through all databases
DECLARE db_cursor CURSOR FOR
SELECT
name
FROM sys.databases
WHERE state_desc = 'ONLINE'
AND name NOT IN ('master', 'tempdb', 'model', 'msdb')
OPEN db_cursor
FETCH NEXT
FROM db_cursor
INTO @DatabaseName
WHILE @@FETCH_STATUS = 0
BEGIN
-- Dynamic SQL to check for the index in the current database
SET
@SQL = '
IF EXISTS (
SELECT 1
FROM [' + @DatabaseName + '].sys.indexes
WHERE name = ''' + @IndexName + '''
AND object_id = OBJECT_ID(''[' + @DatabaseName + '].' + @SchemaName + '.' + @TableName + ''')
)
BEGIN
INSERT INTO #IndexCheckResults (DatabaseName, IndexExists)
VALUES (''' + @DatabaseName + ''', 1)
END
ELSE
BEGIN
INSERT INTO #IndexCheckResults (DatabaseName, IndexExists)
VALUES (''' + @DatabaseName + ''', 0)
END'
EXEC sp_executesql @SQL
FETCH NEXT FROM db_cursor INTO @DatabaseName
END
CLOSE db_cursor
DEALLOCATE db_cursor
-- Select the results
SELECT *
FROM #IndexCheckResults
-- Drop the temporary table
DROP TABLE #IndexCheckResults
Output
The output is a table containing a list of databases, with a boolean column indicating whether or not the index exists in each database. It ran near-enough instantaneously and gave me exactly the information I needed to have confidence that my migration would run without problems on all of our environments.