首页 > 解决方案 > PL/SQL 中的 XMLPATCH?

问题描述

我需要删除 XML 的某些部分(来自 DBMS_METADATA 的表定义)。找到 XMLPATCH 并使其适用于非常小的示例 XML。但我面临两个问题:一大一小。

有谁知道如何优化以下内容以正确删除 /ROWSET[1]/ROW[1]/TABLE_T[1]/CON1_LIST[1] 并使用最少的内存?

有谁知道如何将以下内容重写为 PL/SQL 代码?

SELECT XMLPATCH ( XMLTYPE( '<?xml version="1.0"?>
<ROWSET><ROW><TABLE_T><VERS_MAJOR>2</VERS_MAJOR><MAXTRANS>0</MAXTRANS>
<CON1_LIST><CON1_LIST_ITEM><OWNER_NUM>115</OWNER_NUM></CON1_LIST_ITEM></CON1_LIST>
<BHIBOUNDVAL empty="blob"/><PHYPART_NUM>10</PHYPART_NUM></TABLE_T></ROW></ROWSET>')
                , XMLTYPE( '<?xml version="1.0"?>
<xd:xdiff xsi:schemaLocation="http://xmlns.oracle.com/xdb/xdiff.xsd
 http://xmlns.oracle.com/xdb/xdiff.xsd"
 xmlns:xd="http://xmlns.oracle.com/xdb/xdiff.xsd"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <?oracle-xmldiff operations-in-docorder="true" output-model="snapshot" diff-algorithm="global"?>
    <xd:delete-node 
     xd:node-type="element" 
     xd:xpath="/ROWSET[1]/ROW[1]/TABLE_T[1]/CON1_LIST[1]"/>
</xd:xdiff>')
)
FROM DUAL;
```

标签: xmloracleplsqloracle12coracle-xml-db

解决方案


这个应该解决更大的问题,也应该更快:

select
     XMLQuery('copy $i := $p modify
                  delete nodes $i/ROWSET[1]/ROW[1]/TABLE_T[1]/CON1_LIST[1]
               return $i'
               PASSING XMLTYPE( '<?xml version="1.0"?>
                        <ROWSET>
                           <ROW>
                              <TABLE_T>
                                 <VERS_MAJOR>2</VERS_MAJOR>
                                 <MAXTRANS>0</MAXTRANS>
                                 <CON1_LIST>
                                     <CON1_LIST_ITEM>
                                        <OWNER_NUM>115</OWNER_NUM>
                                     </CON1_LIST_ITEM>
                                 </CON1_LIST>
                                 <BHIBOUNDVAL empty="blob"/>
                                 <PHYPART_NUM>10</PHYPART_NUM>
                              </TABLE_T>
                           </ROW>
                        </ROWSET>') AS "p" 
         RETURNING CONTENT
         ) xres
from dual;

不幸的是,我们仍然在 PL/SQL 中使用 SQL 来更新它:

declare
   x xmltype:= XMLTYPE( '<?xml version="1.0"?>
<ROWSET><ROW><TABLE_T><VERS_MAJOR>2</VERS_MAJOR><MAXTRANS>0</MAXTRANS>
<CON1_LIST><CON1_LIST_ITEM><OWNER_NUM>115</OWNER_NUM></CON1_LIST_ITEM></CON1_LIST>
<BHIBOUNDVAL empty="blob"/><PHYPART_NUM>10</PHYPART_NUM></TABLE_T></ROW></ROWSET>');
   res xmltype;
   g_doc dbms_xmldom.DOMDocument; -- basic DOM-document
   g_node dbms_xmldom.DOMNode;
 
begin
   select
      XMLQuery('copy $i := $p modify
                  delete nodes $i/ROWSET[1]/ROW[1]/TABLE_T[1]/CON1_LIST[1]
               return $i'
               PASSING x AS "p" 
         RETURNING CONTENT
         )
      into res
   from dual;
   dbms_output.put_line(res.getclobval());
end;
/

推荐阅读