Как получить Oracle SCHEMA в виде сценариев DDL с DBMS_METADATA (и SCHEMA_EXPORT)

У меня возникают проблемы с извлечением DDL для данной схемы с помощью DBMS_METADATA, вероятно, из-за того, что я неправильно это понимаю.

Вот что я в основном делаю:

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

У меня сложилось впечатление, что этот метод будет возвращать операторы «CREATE TABLE» в таком порядке, в котором они могут быть созданы, то есть зависимые таблицы будут созданы позже.

Однако оказывается, что порядок таблиц является произвольным в том смысле, что некоторые таблицы создаются с ограничением внешнего ключа, которое ссылается на таблицу, которая не была создана.

Чтобы «решить» эту проблему, я установил для REF_CONSTRAINT и CONSTRAINTS_AS_ALTER значения false и true соответственно, потому что я предполагал, что это устранит мою проблему. Это не так.

Итак, есть ли способ обойти мою проблему или я пропустил какую-то настройку?


person René Nyffenegger    schedule 29.06.2010    source источник
comment
Хороший вопрос. С нетерпением жду ответа.   -  person Rene    schedule 29.06.2010


Ответы (1)


Не столько ответ, сколько наблюдение. Технически возможно (но, вероятно, глупо на практике) иметь циклические ссылки в ограничениях.

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);

Так что я мог бы понять, если бы они решили, что, поскольку это не всегда достижимо, они не стали бы утруждать себя расположением объектов в порядке зависимости.

Таким образом, я бы оставил ссылочные ограничения при создании таблиц, а затем применил их как ALTER после создания всех таблиц.

person Gary Myers    schedule 29.06.2010
comment
Да, я знаю о циклических ссылках и о том, что они запрещают создание таблиц за один раз. Но насколько я понимаю документацию, именно по этой причине для установки REF_CONSTRAINT в false и CONSTRAINTS_AS_ALTER в true так, чтобы ссылочные ограничения не были частью оператора create table, а позже стали отдельным оператором alter table... constraint ... foreign key. - person René Nyffenegger; 30.06.2010