SQLサーバーで大量にある子テーブルのインデックスをまとめて作成する方法
まずは部品化ということでストアドにします。
/*-------------------------------------
ChildTable_IndexKey_Create_20251125
-------------------------------------*/
DROP PROCEDURE IF EXISTS dbo.ChildTable_IndexKey_Create_20251125;
GO
CREATE PROCEDURE dbo.ChildTable_IndexKey_Create_20251125
(@ParentSchema sysname = N'dbo' -- 親テーブルのスキーマ
,@ParentTable sysname -- 親テーブル名
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sql NVARCHAR(MAX) = N'';
DECLARE @parentFullName NVARCHAR(512)
= QUOTENAME(@ParentSchema) + N'.' + QUOTENAME(@ParentTable);
;WITH FKCols AS
(
SELECT DISTINCT
SchemaName = OBJECT_SCHEMA_NAME(fkc.parent_object_id),
TableName = OBJECT_NAME(fkc.parent_object_id),
ColumnName = c.name
FROM sys.foreign_keys fk
JOIN sys.foreign_key_columns fkc
ON fk.object_id = fkc.constraint_object_id
JOIN sys.columns c
ON c.object_id = fkc.parent_object_id
AND c.column_id = fkc.parent_column_id
WHERE fk.referenced_object_id = OBJECT_ID(@parentFullName)
)
SELECT @sql = @sql + '
IF NOT EXISTS (
SELECT 1
FROM sys.indexes i
WHERE i.object_id = OBJECT_ID(N'''
+ QUOTENAME(SchemaName) + N'.' + QUOTENAME(TableName) + N''')
AND i.name = N''' + TableName + N'_Ix_' + ColumnName + N'''
)
BEGIN
CREATE NONCLUSTERED INDEX ' + QUOTENAME(TableName + N'_Ix_' + ColumnName) + N'
ON ' + QUOTENAME(SchemaName) + N'.' + QUOTENAME(TableName) + N'('
+ QUOTENAME(ColumnName) + N');
END
'
FROM FKCols;
-- FK が1つもないケースだと @sql は空文字になるが、その場合は何も起きない
IF (@sql <> N'')
BEGIN
EXEC sp_executesql @sql;
END
END
GO
ストアドを作った後、以下のように利用します。
EXEC ChildTable_IndexKey_Create_20251125 'dbo','Tenant'
GO
EXEC ChildTable_IndexKey_Create_20251125 'dbo','User'
GO