Hystrix


Il mondo è la totalità dei fatti non delle cose.
Archivio Posts
Anno 2018

Anno 2016

Anno 2015

Anno 2009

Anno 2008

Anno 2007

Anno 2006
Statistiche
  • Views Home Page: 56.208
  • Views Posts: 106.317
  • Views Gallerie: 0
  • n° Posts: 41
  • n° Commenti: 84

Drop foreign keys and idexes and recreate it.

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.
Categoria: SQL Server
mercoledì, 03 gen 2007 Ore. 18.08
Calendario
ottobre 2019
lmmgvsd
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910
Ora e Data
Copyright © 2002-2007 - Blogs 2.0
dotNetHell.it | Home Page Blogs
ASP.NET 2.0 Windows 2003