2010-06-29 7 views
8

Ho problemi ad estrarre il DDL per uno schema dato con DBMS_METADATA, probabilmente perché la mia comprensione di ciò è errata.Come ottenere un SCHEMA Oracle come script DDL con DBMS_METADATA (e SCHEMA_EXPORT)

Ecco quello che fondamentalmente faccio:

set termout off 

create table copy_dml_schema(c clob, i number); 

declare 

    m number; 
    t number; 
    e number; 
    c clob; 
    i number := 0; 

begin 

    e := dbms_metadata.session_transform; 


    dbms_metadata.set_transform_param (e, 'REF_CONSTRAINTS'  , false ); 
    dbms_metadata.set_transform_param (e, 'CONSTRAINTS_AS_ALTER', true ); 
    dbms_metadata.set_transform_param (e, 'CONSTRAINTS'   , true ); 
    dbms_metadata.set_transform_param (e, 'FORCE'    , true ); 


    m := dbms_metadata.open('SCHEMA_EXPORT'); 
    t := dbms_metadata.add_transform (m, 'DDL'     ); 

    dbms_metadata.set_transform_param (t, 'PRETTY'    , true ); 
    dbms_metadata.set_transform_param (t, 'SQLTERMINATOR'  , true ); 

    dbms_metadata.set_filter   (m, 'SCHEMA'    , 'XYZ'); 
    dbms_metadata.set_filter   (m, 'EXCLUDE_PATH_EXPR' , 'in (' || 
              '''GRANT''   ,' || 
              '''SYNONYM''  ,' || 
              '''STATISTICS''  ,' || 
              '''COMMENT''   ' || 
              ')'); 


    loop 
    c := dbms_metadata.fetch_clob(m); 
    exit when c is null; 
    insert into copy_dml_schema values (c, i); 
    i := i+1; 
    end loop; 

    dbms_metadata.close(m); 

end; 
/

commit; 


set pages  0 
set trimspool on 
set long  1000000 
set lines   300 
set longchunksize 300 


spool c:\temp\the_schema.sql 

select 
    c 
from 
    copy_dml_schema 
order 
    by i; 

spool off 

drop table copy_dml_schema; 

set termout on 

ho avuto l'impressione che questo metodo sarebbe tornato il bilancio "CREATE TABLE" in tale modo che essi potrebbero essere creati, cioè, tabelle dipendenti sarebbero stati emessi dopo.

Si scopre, tuttavia, che l'ordine delle tabelle è arbitrario in quanto alcune tabelle sono emesse con un vincolo di chiave esterna che fa riferimento a una tabella che non è stata emessa.

Per "risolvere" questo problema, ho impostato il REF_CONSTRAINT e il CONSTRAINTS_AS_ALTER su falso e vero, rispettivamente, perché ho pensato che questo avrebbe risolto il mio problema. Che non è il caso

Quindi, c'è un problema intorno al mio problema o c'è un ambiente che ho trascurato?

+0

Buona domanda. In attesa di risposta. – Rene

risposta

1

Non tanto una risposta quanto un'osservazione. È tecnicamente possibile (ma probabilmente stupido nella pratica) avere riferimenti circolari in vincoli.

create table blue (blue_id number primary key, val varchar2(10), red_id number); 
create table red (red_id number primary key, val varchar2(10), blue_id number); 

insert into blue values (1,'test',2); 
insert into red values (2,'test',1); 

alter table blue add constraint blue_fk foreign key (red_id) references red (red_id); 
alter table red add constraint red_fk foreign key (blue_id) references blue (blue_id); 

Così ho potuto capire se hanno deciso che, in quanto non è necessariamente sempre realizzabile, non avrebbero la briga di mettere gli oggetti in ordine di dipendenza.

Come tale, vorrei lasciare fuori i limiti di riferimento quando vengono create le tabelle, quindi applicarle come ALTER dopo che tutte le tabelle sono state create.

+0

Sì, sono a conoscenza dei riferimenti circolari e che vieterebbero la creazione delle tabelle in una volta sola. Ma per quanto comprendo la documentazione, questo è esattamente il motivo per impostare 'REF_CONSTRAINT' su false e' CONSTRAINTS_AS_ALTER' su true in modo che i vincoli referenziali non facciano parte dell'istruzione 'create table' ma successivamente come' alter table ... vincolo ... dichiarazione di chiave straniera. –

Problemi correlati