Перемещение XML через DBLink - PullRequest
2 голосов
/ 07 июня 2011

Я пытаюсь переместить некоторые данные по ссылке dblink, и один из столбцов является столбцом XMLType. Код выглядит так:

begin
    delete from some_schema.some_remote_tab@src_2_trg_dblink;
    INSERT INTO some_schema.some_remote_tab@src_2_trg_dblink(id, code, gen_date, xml_data)
    SELECT id, code, gen_date, xml_data
    FROM local_table;
end;

Oracle возвращает эти ошибки:

ORA-02055: distributed update operation failed; rollback required
ORA-22804: remote operations not permitted on object tables or user-defined type columns

Некоторые исследования ORA-22804 показывают, что я, вероятно, получаю эту ошибку из-за столбца XMLType, но я не уверен, как ее решить.

(Oracle 10g)

Ответы [ 5 ]

2 голосов
/ 08 июня 2011

Мы получаем ORA-22804, потому что каждый экземпляр Type в нашей базе данных Oracle имеет OID, который является уникальным в базе данных.Мы не можем перенести этот OID в другую базу данных;Это вызывало у меня горе раньше, когда я пытался импортировать схемы с пользовательскими типами.Я не осознавал, что это также влияет на XMLType, но это объект, так что это неудивительно.

Решение странное: вам придется выгрузить XML в текст в локальной базе данных и затем преобразовать еговернуться в XML в удаленной базе данных.

У меня нет распределенной настройки БД, чтобы проверить это прямо сейчас, но если вам повезет, это может сработать:

INSERT INTO some_schema.some_remote_tab@src_2_trg_dblink(id, code, gen_date, xml_data)
SELECT id, code, gen_date, xmltype ( xml_data.asClobVal() )
FROM local_table;

Если метод asClobVal() не 'Вместо этого вам может понадобиться использовать функцию SQL XMLSERIALIZE ().

XMLSerialize(DOCUMENT xml_data AS CLOB) 

Если вам действительно не повезло, вы не сможете сделать это в одном операторе SQL, и у вас будетчтобы решить это с помощью PL / SQL.В определенной степени это будет зависеть от того, какую версию базы данных вы используете;Чем более свежая версия, тем более вероятно, что вы сможете использовать ее в SQL, а не в PL / SQL.

1 голос
/ 07 июня 2011

Попробуй сделать это наоборот. То есть войдите в удаленную базу данных, создайте ссылку на локальную базу данных и выполните вставку, подобную этой:

INSERT INTO remote_schema.some_remote_tab(id, code, gen_date, xml_data) 
SELECT id, code, gen_date, xml_data
    FROM local_table@dblink_to_local_db;
0 голосов
/ 08 августа 2016

Цепочка "xml-> text-> xml" может быть сложной, но может помочь в некоторых случаях (например, когда вставка не включена, а только обновляется).Вы можете попробовать с "n" мирами столбцов varchar (в таблице назначения или в другой сети, что происходит в другой схеме на удаленной БД), где "n": ceil (max (dbms_lob.getlength (MyXmlColumn))) / 4000)

Затем вы можете перенести эти фрагменты в удаленные временные поля:

insert into RemoteSchema.MyTable(Id, XmlPart1, XmlPart2,...)
(select 1 /*some Id*/,
        dbma_lob.substr(MyXmlColumn.getclobval(), 4000, 1),
        dbma_lob.substr(MyXmlColumn.getclobval(), 4000, 4001),
        ...
 from LocalSchema.MyTable

XmlType может быть заново составлен из таких фрагментов:

create or replace function concat_to_xml(p_id number)
return xmltype
is
  xml_lob clob;
  xml xmltype;
begin
  dbms_lob.createtemporary(xml_lob, true);
  for r in (select XmlPart1, XmlPart2, ... from RemoteSchema.MyTable where Id = p_id)
  loop
    if r.XmlPart1 is not null then
      dbms_lob.writeappend(xml_lob, length(r.XmlPart1), r.XmlPart1);
    end if;
    if r.XmlPart2 is not null then
      dbms_lob.writeappend(xml_lob, length(r.XmlPart2), r.XmlPart2);
    end if;
    ...
  end loop;
  xml := xmltype(xml_lob);
  dbms_lob.freetemporary(xml_lob);
  return xml;
end;

Наконец, используйте результат для обновления любой другой таблицы в схеме remothe, например:

update RemoteSchema.MyTable2 t2 set t2.MyXmlColumn = concat_to_xml(1 /*some Id*/);
0 голосов
/ 19 февраля 2016

Я столкнулся с той же проблемой с разнородной ссылкой БД на SQL-сервер.

Завершено использованием xmltype.getStringVal() для вставки в столбец VARCHAR на стороне SQL Server, поскольку данные были меньше 4000 символов.

Существует также xmltype.getClobVal(), если более 4000 символов, но я не проверял его.

0 голосов
/ 22 апреля 2015

Вместо этого выполняйте извлечение данных.

  1. создать процедуру извлечения данных в удаленной базе данных B.
  2. создавать синонимы и предоставлять гранты пользователю dblink.
  3. Вызов процедуры Remote из базы данных A (источник). Выполнение фиксации в базе данных A (источник).

(Между тем ... дождитесь, пока оракул найдет какое-нибудь решение для выполнения PUSH XML через dblink в будущем)

Создать процедуру на удаленном сайте База данных B

CREATE OR REPLACE PROCEDURE PR_REMOTE(OP_TOTAL_COUNT OUT NUMBER) IS
BEGIN

  INSERT /*+ DRIVING_SITE(src) */
  INTO REMOTE_TABLE TGT_B
    (XMLDATA_COL)
    SELECT SRC.XMLDATA FROM LOCAL_TABLE@TGT2SRC_DBLINK SRC;

  OP_TOTAL_COUNT := SQL%ROWCOUNT;

END;

Вызвать процедуру из базы данных A

DECLARE
  V_COUNT NUMBER := 0;
BEGIN
  PR_REMOTE(V_COUNT);
  COMMIT;
END;
...