如何使用DBMS_METADATA(和SCHEMA_EXPORT)获得Oracle SCHEMA的DDL脚本

8
我正在尝试使用DBMS_METADATA提取给定模式的DDL,但可能是因为我的理解有误导致出现问题。
这是我基本上做的事情:
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_CONSTRAINTCONSTRAINTS_AS_ALTER设置为false和true,因为我假设这样会让我的问题消失。但实际上并不是这样的。
那么,有没有解决我问题的方法,或者有我忽略的设置?

好问题。期待答案。 - Rene
1个回答

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

所以我可以理解,如果他们决定不把对象按依赖顺序放置,因为这并不总是可行,他们就不会费心去做。

因此,在创建表时,我会将引用约束条件排除在外,然后在所有表都创建完毕后,再应用它们作为 ALTERs。


是的,我知道循环引用的问题,并且它们会阻止一次性创建表。但据我所了解的文档,这正是将REF_CONSTRAINT设置为false和CONSTRAINTS_AS_ALTER设置为true的原因,以便参照约束不会成为create table语句的一部分,而是稍后作为单独的alter table... constraint ... foreign key语句。 - René Nyffenegger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接