2

我正在尝试通过 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: 分布式更新操作失败;需要回滚
ORA-22804: 不允许对对象表或用户定义类型列进行远程操作

对 ORA-22804 的一些研究表明,由于 XMLType 列,我可能会收到此错误,但我不确定如何解决此问题。

(甲骨文 10g)

4

5 回答 5

2

我们得到 ORA-22804 是因为我们的 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 中使用它。

于 2011-06-08T04:45:22.027 回答
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 回答
1

尝试以相反的方式执行此操作。那就是登录到远程数据库,创建一个到本地数据库的 dblink,然后像这样插入

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 回答
0

" xml->text->xml"链可能很复杂,但在某些情况下可能会有所帮助(例如,当插入不是选项而仅更新时)。您可以尝试使用“n”个 varchar 列和平(在目标表中或在不同的表中,在远程数据库上的不同模式中 perheaps),其中“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;

最后使用结果更新远程模式中的任何其他表,例如:

update RemoteSchema.MyTable2 t2 set t2.MyXmlColumn = concat_to_xml(1 /*some Id*/);
于 2016-08-08T16:37:40.920 回答
0

我遇到了与 SQL Server 的异构数据库链接相同的问题。

最终xmltype.getStringVal()用于在 SQL Server 端插入 VARCHAR 列,因为数据少于 4000 个字符。

还有xmltype.getClobVal()如果超过 4000 个字符,但我还没有测试过。

于 2016-02-19T16:14:23.453 回答