【问题标题】:Moving XML over a DBLink通过 DBLink 移动 XML
【发布时间】:2011-06-07 16:00:26
【问题描述】:

我正在尝试通过 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 列,我可能会收到此错误,但我不确定如何解决此问题。

(Oracle 10g)

【问题讨论】:

    标签: oracle plsql xmltype dblink


    【解决方案1】:

    我们得到 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 中使用它。

    【讨论】:

    • 我已经尝试过xmltype ( xml_data.asClobVal() ),但没有成功,可能是因为表达式的结果仍然是XMLType。最大的问题是在远程将文本 BACK 转换为 XML - 它是供应商拥有的模式......这就是为什么我试图从我这边而不是他们那边做所有事情的原因。 @bpgergo 的解决方案可能效果最好,因为我可以从登录到他们数据库的脚本中运行它,并且 DBLink 已经设置好了。当然,它确实向我们的流程添加了另一个手动步骤...
    【解决方案2】:

    试着反过来做。那就是登录到远程数据库,创建一个到本地数据库的 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;
    

    【讨论】:

    • 它将在该过程中添加另一个手动步骤,但这看起来是最好的方法。没有让 Oracle 允许在 dblink 上使用 XMLTypes...
    【解决方案3】:

    改为执行数据拉取。

    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;
    

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

        【解决方案5】:

        "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*/);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-23
          • 1970-01-01
          • 1970-01-01
          • 2010-11-10
          • 2011-08-05
          • 1970-01-01
          相关资源
          最近更新 更多