2016-02-27 56 views
0

我们有一个名为audit1的表。它有一个包含XML作为blob的“更改”列。 xml如下所示。审计表基本上记录了通过我们的应用程序的用户界面发生的其他表的变化。Oracle - 遍历XMLTYPE和返回节点作为个别行

<c> 
    <f n="VersNo" b="1" a="2"/> 
    <f n="LstDate" b="20160215" a="20160217"/> 
    <f n="FileSweepId" b="Test" a="Test1"/> 
</c> 
  • c代表变化
  • f代表场
  • n属性代表名称(在字段的名字作为)
  • b表示值之前
  • a代表值

我需要创建一个报告,列出所有已发生的变化自给定日期后到某些表格为红色。一旦我有我感兴趣的audit1记录,我需要列出报告中的所有f个节点。

即每个相关审计记录中的每个f节点都需要成为报表中的一行。

该报告由我们的应用程序生成。哪些应用程序可以用于生成报告是下列之一:

  1. 一个SQL查询
  2. 或必须在其中将被传递到过程的SYS REF光标返回其结果的存储过程的名称当应用程序调用它。引用游标将被称为out_cursor。

我想不出一种通过单个SQL查询来实现这一点的方法。所以,我正在写一个存储过程。

  1. 我面临的第一个问题是如何迭代过程中的f个节点。

  2. 其次,我需要弄清楚如何返回这些f节点以及来自out_cursor中审计记录的其他信息。在XQuery的语法错误: LPX-00801:错误解析所述XQuery表达式时 - XPST0003:

    ORA-19114:

     
    BEGIN 
        FOR item IN (SELECT auditno, xmltype(changes, 1) as changes, extract(xmltype(changes, 1), '/c/f') as fields from audit1 where runlistno is null and rownum < 2) 
         LOOP 
         dbms_output.put_line(item.auditno || ' ' || item.changes.getStringVal() || ' ' || item.fields.getStringVal()); 
         -- stumped about how to iterate over the f nodes 
         --FOR field in ('select extractvalue(object_value, '/') x FROM TABLE(XMLSequence(' + item.fields.getStringVal() + ') ') 
        FOR field in (select f from XMLTable('for $i in/return $i' passing item.fields columns f varchar2(200) path 'f')) 
        LOOP 
        dbms_output.put_line(field.f); 
        END LOOP; 
    END LOOP; 
    END; 
    

上述PL /目前误差与SQL 'i'1 for $ i in/return $ i -^ORA-06512:at line 6

回答

0

你为什么不使用简单的SQL,用链式XMLTable函数提取reqired领域?
看简单的例子:

CREATE TABLE audit1(
    changes CLOB 
); 

INSERT INTO audit1 VALUES('<c> 
    <f n="VersNo" b="1" a="2"/> 
    <f n="LstDate" b="20160215" a="20160217"/> 
    <f n="FileSweepId" b="Test" a="Test1"/> 
</c>' 
); 
INSERT INTO audit1 VALUES(
'<c> 
    <f n="VersNo" b="22" a="32"/> 
    <f n="LstDate" b="20160218" a="2016020"/> 
    <f n="FileSweepId" b="Test 555" a="Test1234"/> 
</c>' 
); 
commit; 

现在:

SELECT rec_no, rn, n, b, a 
FROM (select rownum rec_no, a.* FROM audit1 a), 
    XMLTable('/c' 
       passing xmltype(changes) 
       columns f_fields xmltype path './f' 
      ) x1, 
    XMLTable('/f' 
       passing x1.f_fields 
       columns rn for ordinality, 
         n varchar2(20) path './@n', 
         b varchar2(20) path './@b', 
         a varchar2(20) path './@a' 
       ) 

    REC_NO   RN N     B     A     
---------- ---------- -------------------- -------------------- -------------------- 
     1   1 VersNo    1     2      
     1   2 LstDate    20160215    20160217    
     1   3 FileSweepId   Test     Test1     
     2   1 VersNo    22     32     
     2   2 LstDate    20160218    2016020    
     2   3 FileSweepId   Test 555    Test1234    

6 rows selected 
0

我能够摆脱o f通过修改plsql的错误:

BEGIN 
    FOR item IN (SELECT auditno, xmltype(changes, 1) as changes, extract(xmltype(changes, 1), '/c/f') as fields from audit1 where runlistno is null and rownum < 2) 
    LOOP 
    dbms_output.put_line('parsing fields from: ' || item.fields.getStringVal()); 
    dbms_output.put_line('name||beforevalue||aftervalue'); 
    FOR field in (select n, b, a from XMLTable('//f' passing item.fields columns n varchar2(30) path '@n', b varchar(30) path '@b', a varchar(30) path '@a')) 
     LOOP 
     dbms_output.put_line(field.n || '|| ' || field.b || '|| ' || field.a); 
    END LOOP; 
    END LOOP; 
END; 

所以我现在能够遍历字段。但不知道如何我可以返回系统参考游标中的字段的信息。从上面PLSQL输出例如:

parsing fields from: <f n="VersNo" b="1" a="2"/><f n="LstDate" b="20160215" a="20160217"/><f n="FileSweepId" b="Test" a="Test1"/> 
name||beforevalue||aftervalue 
VersNo|| 1|| 2 
LstDate|| 20160215|| 20160217 
FileSweepId|| Test|| Test1