In questi giorni mi trovo alle prese con la pubblicazione di un db SQL 2000 non piccolissimo [12 GB]. In sviluppo ho il nuovo db, in produzione c'è quello vecchio. Il nuovo db è pronto, mi restano da trasferire i dati.
Il db è abbastanza complesso e la nuova versione presenta importanti novità. Gli script di trasferimento dati sono necessariamente scritti ad hoc ma sorge un problema.
Gli indici e le relazioni rendono sia la fase di sviluppo degli script di trasferimento che la fase di produzione vera e propria molto molto lenti. Se riuscissi a sbarazzarmi in questa fase delgi indici e delle relazioni potre sfruttare inserimenti molto rapidi e efficienti truncate table. Ma come creare tutti gli script di distruzione e creazione di indici e relazioni?
Non ho trovato nulla, quindi mi sono construito i piccoli script che seguono.
Tali script non sono direttamente "pericolosi" poichè semplicemente producono script e non toccano in alcun modo il db.
Al contrario il codice prodotto è decisamente pericoloso e da maneggiare con cura, se a qualcuno interessasse usarli si assuma completamente la responsabilità di ciò che fa. :-D
Un ultima cosa, gli script contiengono assunzioni arbitrarie adatte alle mie scelte [tutti gli indici sono creati con l'opzione padindex e tutte le relazioni sono "not for replication"].
Sono tuttavia facilmente adattabili a scelte differenti.
Creazione/Distruzione di indici e vincoli PK e univici:
create function __XGetIndexFields(@id int, @name sysname)
returns varchar(8000)
as
begin
declare @r varchar(8000)
select @r=isnull(@r+', ','') + quotename(c.name)
from sysindexkeys k
inner join sysindexes i
on i.id=k.id and i.indid=k.indid
inner join syscolumns c
on c.id=k.id and c.colid=k.colid
where i.id=@id and i.name=@name
order by k.keyno
return @r
end
go
declare @MinFillFactor int,@Create bit
/*@MinFillFactor permette di specificare un fillfactor minimo, pensato tipicamente per quegli indici per cui non è stato impostato alcun valore*/
set @MinFillFactor=80
/*@Create definisce se vadano prodotti gli script di creazione degli indici o di drop*/
set @Create=1
select
case when c.id is null then
case @Create when 1 then
'create ' +
case indexproperty(i.id,i.name,'IsUnique') when 1 then 'unique ' else '' end +
case indexproperty(i.id,i.name,'IsClustered') when 1 then 'clustered' else 'nonclustered' end
+' index '+ i.name + ' on ' + quotename(o.name) + ' (' + dbo.__XGetIndexFields(i.id,i.name) + ')' +
+ ' with fillfactor = ' + case when indexproperty(i.id,i.name,'IndexFillFactor')<@MinFillFactor then '80' else convert(varchar,indexproperty(i.id,i.name,'IndexFillFactor')) end + ', pad_index'
else
'drop index ' + quotename(o.name) + '.' + quotename(i.name)
end
else
'alter table ' + quotename(o.name) +
case @Create when 1 then
' add constraint ' + quotename(i.name) +
case when objectproperty(c.constid,'IsPrimaryKey')=1 then ' primary key' else ' unique' end +
case indexproperty(i.id,i.name,'IsClustered') when 1 then ' clustered' else '' end
+ ' (' + dbo.__XGetIndexFields(i.id,i.name) + ')' +
+ ' with fillfactor = ' + case when indexproperty(i.id,i.name,'IndexFillFactor')<@MinFillFactor then '80' else convert(varchar,indexproperty(i.id,i.name,'IndexFillFactor')) end
else
' drop constraint ' + quotename(i.name)
end
end
from sysindexes i
inner join sysobjects o
on o.id=i.id
left outer join sysconstraints c
on c.id=o.id and object_name(c.constid)=i.name
where o.xtype in('U','V') and indexproperty(i.id,i.name,'IsStatistics')=0 and dbo.__XGetIndexFields(i.id,i.name) is not null
order by i.id,i.indid*case @Create when 1 then 1 else -1 end
go
drop function __XGetIndexFields
Creazione/distruzione relazioni:
create function __XGetForeignKeysFileds(@kid int,@f bit)
returns varchar(8000)
as
begin
declare @r varchar(8000)
select @r=isnull(@r+', ','') + case @f when 1 then quotename(fc.name) else quotename(rc.name) end
from sysforeignkeys k
inner join syscolumns fc
on fc.colid=k.fkey and fc.id=k.fkeyid
inner join syscolumns rc
on rc.colid=k.rkey and rc.id=k.rkeyid
where k.constid=@kid
order by k.keyno
return @r
end
go
declare @Create bit
/*@Create definisce se vadano prodotti gli script di creazione delle relazioni o di drop*/
set @Create=0
select 'alter table ' + quotename(fname) +
case @Create when 1 then
'add constraint ' + quotename(kname) + 'foreign key(' + dbo.__XGetForeignKeysFileds(constid,1)+') references ' + quotename(rname)+'(' + dbo.__XGetForeignKeysFileds(constid,0) +')'
+ case when objectproperty(constid,'CnstIsDeleteCascade')=1 then ' on delete cascade' else '' end
+ case when objectproperty(constid,'CnstIsUpdateCascade')=1 then ' on update cascade' else '' end
+ ' not for replication'
else
'drop constraint ' + quotename(kname)
end
from(
select distinct fo.name fname,ro.name rname,ko.name kname,k.constid
from sysforeignkeys k
inner join sysobjects ko
on ko.id=k.constid
inner join sysobjects fo
on fo.id=k.fkeyid
inner join sysobjects ro
on ro.id=k.rkeyid)v
order by fname
go
drop function __XGetForeignKeysFileds
marc.