2

一部のデータをdblink経由で移動しようとしていますが、列の1つが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:分散更新操作が失敗しました。ロールバックが必要
ORA-22804:オブジェクト表またはユーザー定義型列でのリモート操作は許可されていません

ORA-22804に関するいくつかの調査によると、XMLType列が原因でこのエラーが発生している可能性がありますが、これを解決する方法がわかりません。

(Oracle 10g)

4

5 に答える 5

2

Oracleデータベース内のTypeのすべてのインスタンスにはデータベース内で一意のOIDがあるため、ORA-22804が取得されます。そのOIDを別のデータベースに転送することはできません。これにより、ユーザー定義型のスキーマをインポートしようとする前に、私は悲しみを覚えました。XMLTypeにも影響があることに気づいていませんでしたが、オブジェクトなので驚くことではありません。

解決策は厄介です。ローカルデータベースでXMLをテキストにアンロードしてから、リモートデータベースでXMLに変換し直す必要があります。

現在、これをテストするための分散DBセットアップはありませんが、運が良ければうまくいく可能性があります。

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を使用して解決する必要があります。ある程度、これは使用しているデータベースのバージョンによって異なります。バージョンが新しいほど、PL/SQLではなくSQLで使用できる可能性が高くなります。

于 2011-06-08T04:45:22.027 に答える
1

これを逆にしてみてください。つまり、リモートデータベースにログインし、ローカルデータベースへのデータベースリンクを作成して、次のような挿入を行います。

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;
于 2011-06-07T16:17:25.130 に答える
1

代わりに、データプルを実行してください。

  1. リモートデータベースBでデータプルプロシージャを作成します。
  2. 同義語を作成し、dblinkユーザーに許可を提供します。
  3. データベースA(ソース)からリモートプロシージャを呼び出すデータベースA(ソース)でコミットを実行します。

(その間、.. oracleが将来dblinkを介してXMLのPUSHを実行するための解決策を見つけるのを待ちます)

リモートサイトデータベース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;
于 2015-04-22T03:52:19.980 に答える
0

SQLサーバーへの異種DBリンクで同じ問題に直面していました。

xmltype.getStringVal()データが4000文字未満だったため、SQLServer側のVARCHAR列に挿入するために使用することになりました。

4000文字を超える場合もありますがxmltype.getClobVal()、テストしていません。

于 2016-02-19T16:14:23.453 に答える
0

xml->text->xml」チェーンは複雑な場合がありますが、場合によっては役立つことがあります(たとえば、挿入がオプションではなく更新のみの場合)。varchar列の「n」個のピース​​(宛先テーブルまたは別のテーブル、リモートDBの別のスキーマでパーヒープ)を試すことができます。ここで、「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*/);
于 2016-08-08T16:37:40.920 に答える