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_CONSTRAINTandCONSTRAINTS_AS_ALTER分别设置为 false 和 true,因为我认为这会让我的问题消失。事实并非如此。

那么,是否可以解决我的问题,或者是否有我忽略的设置?

4

1 回答 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);

所以我可以理解他们是否决定这样做,因为它不一定总是可以实现的,他们不会费心将对象按依赖顺序排列。

因此,我会在创建表时将引用约束排除在外,然后在创建所有表后将它们作为 ALTER 应用。

于 2010-06-29T23:06:39.533 回答