Есть хороший обходной путь к проблеме Oracle IMPDP REMAP_SCHEMA с триггерами (ORA-39083, ORA-00942)? - PullRequest
8 голосов
/ 26 января 2010

Можно использовать инструмент импорта Oracle data pump (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 ...

Причина этого в том, что SQL для создания по-прежнему ссылается на OLD_SCHEMA. В документации Oracle говорится:

Отображение не может быть на 100 процентов завершить, потому что есть определенные Схема ссылается на то, что импорт не является способен найти. Например, Импорт не найдет ссылки на схемы встроен в тело определения типов, представлений, процедуры и пакеты.

ИМХО, это немного похоже на Oracle, но это другое обсуждение!

Согласно Oracle Metalink note 750783.1, обходной путь:

  1. Создайте SQLFILE для включения соответствующих команд DDL:
      impdp system/****** directory=test_dp
      DUMPFILE=export_schemas.dmp
     remap_schema=u1:u2 sqlfile=script.sql
  1. Извлеките затронутый DDL из написанного SQLFILE и исправьте ссылка на схему. Затем выполните команду вручную.

Это не очень хороший способ сделать это, особенно если у вас много отказавших объектов и вы хотите автоматизировать процесс объединения нескольких схем для обновления баз данных на местах.

Кто-нибудь нашел лучший способ сделать это? Мне нужно решение, которое должно быть на 100% надежным, если оно будет использоваться в полевых условиях. Я мог бы разобрать сгенерированный файл SQL, но можно ли получить это 100% правильно? Нет ли способа перехватить операторы CREATE SQL, выполняемые IMPDP, и исправить их на лету при импорте? Можно ли исправить файл DMP напрямую?

Ответы [ 2 ]

0 голосов
/ 14 сентября 2017

Я думаю, это зависит от того, могут ли имена схем появляться в вашем коде как часть чего-то, что не является именем схемы. Например, есть ли у вас имена переменных, которые содержат те же символы, что и имя схемы. Если нет, то я не думаю, что было бы так сложно составить сценарий процесса, который редактирует сгенерированные триггеры, создавая сценарии, заменяя старую схему новой. Возможно, вы можете использовать datapump для экспорта / импорта типов объектов, которые не имеют текстового кода (не триггеры, пакеты, процедуры, функции и т. Д.), А затем вывести SQL-код для объектов кода и просто заменить старую схему новой. .

Если имя старой схемы появляется в местах, которые вы не хотите заменять, сделать это будет сложнее. Вы можете извлечь объекты кода и попытаться создать их и собрать все ошибки. Затем получите имена объектов, на которых произошел сбой, и попробуйте заменить oldschema.objectname на newschema.objectname, основываясь на ошибках, и выполните повторный запуск.

Пример того, как вы можете редактировать схему в тексте триггера, предполагая, что не было строк, подобных oldschema. что вы не хотите заменять:

Пример

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
0 голосов
/ 27 января 2010

Вы можете посмотреть DBMS_METADATA

Для этого есть опция REMAP_SCHEMA . Не уверен, будет ли он работать лучше, чем DATAPUMP (и я подозреваю, что DATAPUMP будет использовать DBMS_METADATA под крышками). Но было бы легче «постобработать» вывод.

...