我在使用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','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,因为我认为这会让我的问题消失.事实并非如此.
那么,是否有解决我的问题的办法,还是有一个我忽略的设置?
而不是作为一种观察的答案.
在技术上可能(但在实践中可能是愚蠢的)在约束中具有循环引用.
在技术上可能(但在实践中可能是愚蠢的)在约束中具有循环引用.
create table blue (blue_id number primary key,val varchar2(10),red_id number); create table red (red_id number primary key,blue_id number); insert into blue values (1,'test',2); insert into red values (2,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.