Mi è giusto capitato pochi giorni fa e
per risolvere il problema mi sono creato una Stored Procedure che esegue :
- Salvataggio metadati di tutte le Fk della tabella
- Drop di tutte le Fk dalla tabella
- Disable di tutti gli indici
- Salvataggio metadati indice clustered
- Drop Indice clustered dalla tabella
- Create indice clustered con i metadati salvati precedentemente sul nuovo filegroup
- Rebuild Indici non-clustered
- Create FK con i metadati salvati precedentemente
--N.B. MODIFICARE IL NOME DEL DB PRIMA DI USARE LO SCRIPT
Use TestMoveTable
Go
--N.B. MODIFICARE IL NOME DELLA TABELLA E DEL FILEGROUP
Declare @TabToMove varchar(128) = '[dbo].[TableFK]'
Declare @FileGroup varchar(128) = 'NEWFG'
Declare @Disable_Index varchar(max) = 'Alter index ALL on ' + @TabToMove + ' Disable;'
Declare @Drop_Clustered_Index varchar(max) = ''
Declare @Create_Clustered_Index varchar(max) = ''
Declare @Rebuild_NonClustered_Index varchar(max) = ''
Declare @Create_Fk varchar(max) = ''
Declare @Drop_Fk varchar(max) = ''
Select @Drop_Fk+= drop_command +';' + char(13) + char(10) From
(
select
'ALTER TABLE '
+ QUOTENAME(Object_Name(FKC.Parent_object_id)) + ' DROP CONSTRAINT '
+ QUOTENAME(Object_name(FKC.constraint_object_id)) DROP_COMMAND
from sys.foreign_key_columns FKC
Inner Join sys.columns CP
ON CP.object_id = FKC.parent_object_id
AND CP.column_id = FKC.parent_column_id
Inner Join sys.columns RCP
ON RCP.object_id = FKC.Referenced_object_id
AND RCP.column_id = FKC.Referenced_column_id
Inner join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS Const
ON Const.CONSTRAINT_NAME = Object_name(FKC.constraint_object_id)
Where FKC.referenced_object_id = Object_ID(@TabToMove)
)Drop_Command
Select @Create_Fk+= create_command +';' + char(13) + char(10) From
(
select
'ALTER TABLE '
+ QUOTENAME(Object_Name(FKC.Parent_object_id)) + ' WITH CHECK ADD CONSTRAINT '
+ QUOTENAME(Object_name(FKC.constraint_object_id)) + ' FOREIGN KEY ('
+ QUOTENAME(CP.name) + ') REFERENCES ' + QUOTENAME(Object_Name(FKC.Referenced_object_id))
+ '(' + QUOTENAME(RCP.name) + ')'
+ CASE WHEN Const.UPDATE_RULE = 'CASCADE' THEN ' ON UPDATE CASCADE ' ELSE '' END
+ CASE WHEN Const.UPDATE_RULE = 'CASCADE' THEN ' ON DELETE CASCADE ' ELSE '' END CREATE_COMMAND
from sys.foreign_key_columns FKC
Inner Join sys.columns CP
ON CP.object_id = FKC.parent_object_id
AND CP.column_id = FKC.parent_column_id
Inner Join sys.columns RCP
ON RCP.object_id = FKC.Referenced_object_id
AND RCP.column_id = FKC.Referenced_column_id
Inner join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS Const
ON Const.CONSTRAINT_NAME = Object_name(FKC.constraint_object_id)
Where FKC.referenced_object_id = Object_ID(@TabToMove)
)Create_Command
Select @Rebuild_NonClustered_Index = @Rebuild_NonClustered_Index + char(13) +char(10) + Rebuild_Index + ';' From
(
select 'Alter Index '+ Quotename(i.name) + ' on ' + @TabToMove + ' Rebuild'
Rebuild_Index
from sys.indexes as i
inner join sys.objects obj
on i.object_id=obj.object_id
inner join sys.schemas sch
on obj.schema_id=sch.schema_id
inner join sys.partitions part
on i.object_id=part.object_id
and i.index_id=part.index_id
inner join sys.stats stats
on i.object_id=stats.object_id
and i.index_id=stats.stats_id
where i.object_id = object_id(@TabToMove)
And I.type_desc = 'NONCLUSTERED'
)A
Select @Drop_Clustered_Index = Drop_Index From
(
select Case When is_primary_key = 1 Or is_unique_constraint = 1 Then 'Alter Table ' + @TabToMove + ' Drop constraint ' + Quotename(i.name)
else 'Drop index ' + Quotename(i.name) + ' on ' + @TabToMove + ';'
End Drop_Index
from sys.indexes as i
inner join sys.objects obj
on i.object_id=obj.object_id
inner join sys.schemas sch
on obj.schema_id=sch.schema_id
inner join sys.partitions part
on i.object_id=part.object_id
and i.index_id=part.index_id
inner join sys.stats stats
on i.object_id=stats.object_id
and i.index_id=stats.stats_id
where i.object_id = object_id(@TabToMove)
And I.type_desc = 'CLUSTERED'
)A
Select @Create_Clustered_Index = Create_Index from
(
Select Case is_primary_key When 1 Then 'Alter Table ' + @TabToMove + ' Add constraint ' + index_name + ' Primary Key Clustered (' + reverse(stuff(reverse(index_columns), 1, 1, '')) + ') on ' + @FileGroup + ';'
else
Case is_unique_constraint when 1
Then 'Alter Table ' + @TabToMove + ' Add constraint ' + index_name + ' Unique Clustered (' + reverse(stuff(reverse(index_columns), 1, 1, '')) + ') on ' + @FileGroup + ';'
else
Case Is_unique When 1
Then 'Create Unique Clustered index ' + Quotename(index_name) + ' on ' + @TabToMove + '(' + reverse(stuff(reverse(index_columns), 1, 1, '')) + ') on ' + @FileGroup + ';'
Else
'Create Clustered index ' + Quotename(index_name) + ' on ' + @TabToMove + '(' + reverse(stuff(reverse(index_columns), 1, 1, '')) + ') on ' + @FileGroup + ';'
End
End
End Create_Index
from
(
select
quotename(sch.name)+'.'+quotename(obj.name) [table_name],
quotename(i.name) [index_name],
i.type_desc,
(
select '['+col.name+'] '
+ Case is_descending_key When 1 then ' Desc,'
Else 'Asc,'
End as [data()]
from sys.index_columns as k
inner join sys.columns col
on k.object_id=col.object_id
and k.column_id=col.column_id
where k.object_id = i.object_id
and k.index_id = i.index_id
and k.index_id<>0
and k.is_included_column<>1
order by key_ordinal, k.column_id
for xml path('')
)
as [index_columns],
is_unique,
is_primary_key,
is_unique_constraint,
fill_factor,
is_padded
from sys.indexes as i
inner join sys.objects obj
on i.object_id=obj.object_id
inner join sys.schemas sch
on obj.schema_id=sch.schema_id
inner join sys.partitions part
on i.object_id=part.object_id
and i.index_id=part.index_id
inner join sys.stats stats
on i.object_id=stats.object_id
and i.index_id=stats.stats_id
where i.object_id = object_id(@TabToMove)
And I.type_desc = 'CLUSTERED'
)A
)B
Print @Drop_Fk
Print @Disable_Index
Print @Drop_Clustered_Index
Print @Create_Clustered_Index
Print @Rebuild_NonClustered_Index
Print @Create_Fk
Lo script genera un risultato simile a questo nella finestra Messages :
Attenzione, non eseguire lo script su tabelle partizionate....
Ciao
Luca
Nessun commento:
Posta un commento