首页 文章

有关触发器(ORA-39083,ORA-00942)的Oracle IMPDP REMAP_SCHEMA问题是否有一个很好的解决方法?

提问于
浏览
8

可以使用Oracle数据泵导入工具(IMPDP.EXE)使用REMAP_SCHEMA选项将一个模式导入另一个模式 . 但是,存在一个问题,即触发器未正确重新映射 . 这导致触发器根本没有创建错误,如下所示:

ORA-39083: Object type TRIGGER failed to create with error: ORA-00942: table or view does not exist Failing sql is: CREATE TRIGGER "**NEW_SCHEMA**"."METER_ALARMS_BI"   BEFORE INSERT ON
**OLD_SCHEMA**.METER_ALARMS ...

原因是因为create SQL仍然引用OLD_SCHEMA . 它确实在Oracle文档中说:

映射可能不是100%完成,因为某些模式引用导入无法查找 . 例如,Import将找不到嵌入在类型,视图,过程和包的定义主体中的模式引用 .

恕我直言,这是甲骨文的一个警察,但这是另一个讨论!

根据Oracle Metalink说明750783.1,解决方法是:

创建一个SQLFILE以包含相关的DDL命令:

impdp system/****** directory=test_dp
      DUMPFILE=export_schemas.dmp
     remap_schema=u1:u2 sqlfile=script.sql

从写入的SQLFILE中提取受影响的DDL并更正模式引用 . 然后手动执行该命令 .

这不是一个好方法,特别是如果你有许多失败的对象,并希望自动化组合多个模式的过程,以便在数据库的字段升级 .

有没有人找到更好的方法来做到这一点?如果要在现场使用,我需要一个必须100%可靠的解决方案 . 我可以解析生成的SQL文件,但可以100%正确吗?是否有一些方法可以拦截IMPDP执行的CREATE SQL语句并在导入时动态更正?可以直接修补DMP文件吗?

2 回答

  • 0

    你可以看一下DBMS_METADATA

    有一个REMAP_SCHEMA选项 . 不确定它是否会比DATAPUMP(并且我'd suspect that DATAPUMP would use DBMS_METADATA under the covers). But it would be easier to '后处理'输出更好) .

  • 0

    我认为这取决于模式名称是否可以作为非模式名称的一部分出现在您的代码中 . 例如,您是否具有包含与模式名称相同的字符的变量名称 . 如果没有,那么我认为编写生成的触发器创建脚本替换旧模式的进程的脚本编写起来并不困难 . 也许你可以使用datapump导出/导入没有文本代码的对象类型(不是触发器,包,程序,函数等),然后为代码对象转储SQL,只需用新的替换旧模式 .

    如果旧模式名称出现在您不想替换的位置,则会更难 . 您可以提取代码对象并尝试创建它们并收集所有错误 . 然后获取失败的对象的名称,并尝试使用newschema.objectname根据错误替换oldschema.objectname并重新运行 .

    假设没有像oldschema这样的字符串,您可以在触发器文本中编辑模式的示例 . 你不想要替换:

    Example

    SQL> 
    SQL> set define off
    SQL> 
    SQL> drop table test1.tab1;
    
    Table dropped.
    
    SQL> drop table test1.tab2;
    
    Table dropped.
    
    SQL> 
    SQL> create table test1.tab1
      2  (
      3     col1 number,
      4     col2 number
      5  );
    
    Table created.
    
    SQL> 
    SQL> create table test1.tab2
      2  (
      3     col1 number,
      4     col2 number
      5  );
    
    Table created.
    
    SQL> 
    SQL> create or replace trigger test1.trg1
      2  before insert or update on test1.tab1
      3  for each row
      4  begin
      5    :new.col2 := :new.col1*2;
      6  end;
      7  /
    
    Trigger created.
    
    SQL> 
    SQL> create or replace trigger test1.trg2
      2  before insert or update on test1.tab2
      3  for each row
      4  begin
      5    :new.col2 := :new.col1*2;
      6  end;
      7  /
    
    Trigger created.
    
    SQL> 
    SQL> drop table clobout;
    
    Table dropped.
    
    SQL> 
    SQL> create table clobout (doc clob);
    
    Table created.
    
    SQL> 
    SQL> declare
      2  h NUMBER; --handle returned by OPEN
      3  th NUMBER; -- handle returned by ADD_TRANSFORM
      4  doc CLOB;
      5  BEGIN
      6  
      7  -- Specify the object type.
      8  h := DBMS_METADATA.OPEN('TRIGGER');
      9  
     10  -- Use filters to specify the particular object desired.
     11  DBMS_METADATA.SET_FILTER(h,'SCHEMA','TEST1');
     12  
     13  -- Request that the schema name be modified.
     14  th := DBMS_METADATA.ADD_TRANSFORM(h,'MODIFY');
     15  DBMS_METADATA.SET_REMAP_PARAM(th,'REMAP_SCHEMA','TEST1','TEST2');
     16  
     17  -- Request that the metadata be transformed into creation DDL.
     18  th := DBMS_METADATA.ADD_TRANSFORM(h,'DDL');
     19  
     20  dbms_metadata.set_transform_param(th,'SQLTERMINATOR',true);
     21  
     22  -- Fetch the triggers.
     23  
     24  LOOP
     25    doc := DBMS_METADATA.FETCH_CLOB(h);
     26    EXIT WHEN (doc is null);
     27    insert into clobout values (doc);
     28    commit;
     29  END LOOP;
     30  
     31  -- Release resources.
     32  DBMS_METADATA.CLOSE(h);
     33  END;
     34  /
    
    PL/SQL procedure successfully completed.
    
    SQL> 
    SQL> -- update schema name in triggers
    SQL> 
    SQL> update clobout set doc=replace(doc,'test1.','test2.');
    
    2 rows updated.
    
    SQL> 
    SQL> commit;
    
    Commit complete.
    
    SQL> 
    SQL> select doc from clobout;
    
      CREATE OR REPLACE EDITIONABLE TRIGGER "TEST2"."TRG1"
    before insert or update on test2.tab1
    for each row
    begin
      :new.col2 := :new.col1*2;
    end;
    /
    ALTER TRIGGER "TEST2"."TRG1" ENABLE;
    
    
      CREATE OR REPLACE EDITIONABLE TRIGGER "TEST2"."TRG2"
    before insert or update on test2.tab2
    for each row
    begin
      :new.col2 := :new.col1*2;
    end;
    /
    ALTER TRIGGER "TEST2"."TRG2" ENABLE;
    
    
    SQL> 
    SQL> spool off
    

相关问题