【问题标题】:ExtractValue/xmlsequence提取值/xmlsequence
【发布时间】:2015-11-14 12:36:05
【问题描述】:

我有以下代码,它适用于它提取的较小数据,但是当它遇到更大尺寸的记录时,它会出错。我将如何解决 ORA-01706:user function result value is too large 错误?

FOR r IN
          (SELECT Extract(Value(p),'pmt:PayInfo/pmt:Single', r_namespace) As Address,
          ExtractValue(Value(p),'pmt:PayInfo/pmt:Single/pmt:SingExtRef', r_namespace) AS extref,
          ExtractValue(Value(p),'pmt:PayInfo/pmt:Single/pmt:SingSequence', r_namespace) AS singseq
          FROM TABLE(XMLSequence(Extract(payXml,'/abcd:abcd/abcd:Pmt/pmt:Payments/pmt:PayInfo['||ctr2||']', r_namespace))) p
          )
          LOOP
          FOR row1 IN
            (SELECT ExtractValue(Value(l),'/pmt:SingAddInfo/cmn:AddInfoCmpType/text()', r_namespace) AS singtype,
    ExtractValue(Value(l),'/pmt:SingAddInfo/cmn:AddInfoCmpText[1]/text()', r_namespace) AS singtext1,
    ExtractValue(Value(l),'/pmt:SingAddInfo/cmn:AddInfoCmpText[2]/text()', r_namespace) AS singtext2,
          FROM TABLE(XMLSequence(Extract(r.Address,'/pmt:Single/pmt:SingAddInfo', r_namespace))) l
            )
            LOOP 
         IF (row1.singtype = 'IATCode')
         THEN
         r_iatcode := row1.singtext1;
         r_iatcode2 := row1.singtext2;
         ELSIF (row1.singtype = 'IndivID')
         THEN
         r_payor_identifier := row1.singtext1;
    END IF;
    END LOOP;
    END LOOP;

感谢您的宝贵时间!

【问题讨论】:

  • 你认为什么是“更大的”?你有一个迹象,例如XML 的文件大小?
  • 好吧,传递给 oracle SP 本身的规范是 10300 行(一个巨大的文件)。但是正在爆炸的部分(即上面执行提取的代码部分)占该文件的 90%,我会说。只需将其视为工资单记录,公司信息占 10%,工资单信息占其余 90%。它是,或者我应该说,可能是一个大文件,只是发现当文件大小达到那里时它会爆炸。
  • 问题是当你使用像 ExtractValue 这样的函数时,整个 XML 文档必须加载到内存中(DOM,文档对象模型)。它会产生巨大的开销,因此无法使用更大的文件或花费很长时间。对于更大的 XML 文档,您应该更喜欢基于流/事件的 XML 解析器(例如 SAX,XML 的简单 API)。但是,我不知道这是否可以通过任何 Oracle XML 函数直接完成。
  • 谢谢温弗里德。还有其他可以帮助我的人吗?感谢您的时间。
  • 如果您使用的是 Oracle 11g,您可以尝试 DBMS_XMLDOM 和 DBMS_XMLPARSER API。自己没有尝试过,但似乎是使用流进行 XML 处理(docs.oracle.com/cd/B28359_01/appdev.111/b28369/xdb10pls.htm)。

标签: sql oracle plsql oracle-xml-db


【解决方案1】:

当你得到ORA-01706: user function result value was too large 并且你正在使用EXTRACTVALUE() 这是因为这个函数最多只能返回一个VARCHAR2(4000 CHAR) 结果。

下面是一个简化的通用示例。

遇到超过 4000 个字符的“VALUES”节点时会中断:

SELECT pk,
       EXTRACTVALUE(VALUE(xml), '*/VALUES') as vals
  FROM tableName a,
       TABLE (XMLSEQUENCE (EXTRACT (a.xmlFieldName, '/SOME/PATH/*'))) xml
 WHERE s.pk = 1         
   AND EXTRACTVALUE(VALUE(xml), '*/VALUES') IS NOT NULL;

改用以下语法,您可以定义您期望的 CLOB 结果,这将起作用:

SELECT pk,
       xml.vals
  FROM tableName a,
       XMLTable('/SOME/PATH/*'
                PASSING a.xmlFieldName
                COLUMNS vals     CLOB    PATH   'VALUES/text()') xml
 WHERE a.pk = 1
   AND xml.vals IS NOT NULL;

以上示例是当 XML 存储在表中的 XMLType 列中时。如果您使用的是本地 PL/SQL 变量而不是表,您可以这样做:

SELECT xml.vals
  FROM XMLTable('/SOME/PATH/*'
                PASSING local_xmltype_variable
                COLUMNS vals     CLOB    PATH   'VALUES/text()') xml
 WHERE xml.vals IS NOT NULL;

【讨论】:

    猜你喜欢
    • 2021-05-18
    • 1970-01-01
    • 2015-07-24
    • 2019-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    相关资源
    最近更新 更多