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

时间:2010-01-26 09:06:38

标签: oracle schema remap ora-00942 impdp

一个可以使用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%   完成,因为有一定的   导入不是的模式引用   能够找到。例如,   导入将找不到架构引用   嵌入体内   类型,观点的定义,   程序和包。

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

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

  
      
  1. 创建一个SQLFILE以包含相关的DDL命令:
  2.   
      impdp system/****** directory=test_dp
      DUMPFILE=export_schemas.dmp
     remap_schema=u1:u2 sqlfile=script.sql
  
      
  1. 从写入的SQLFILE中提取受影响的DDL并更正   架构参考。然后手动执行命令。
  2.   

这不是一个好方法,特别是如果您有许多失败的对象,并且想要在数据库的现场升级中自动组合多个模式的过程。

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

2 个答案:

答案 0 :(得分:0)

您可以查看DBMS_METADATA

有一个REMAP_SCHEMA选项。不确定它是否会比DATAPUMP更好(我怀疑DATAPUMP将使用DBMS_METADATA)。但是对输出进行“后处理”会更容易。

答案 1 :(得分: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