如何在PL / SQL中通过XML进行循环

时间:2017-02-10 17:29:45

标签: sql xml oracle plsql

我的XML看起来像这样:

<root>
  <row>
    <grade>A</grade>
    <Employee>
      <Name>ROBERT SUKIMIN</Name>
      <company>ABC</company>     
    </Employee>
    <Group>117761020</Group>
    <Designation>2014-03-21</Designation>
    <Company_code>5813044</Company_code>
  </row>
  <row>
    <grade>B</grade>
    <Employee>
      <Name>CECIL PAINEM</Name>
      <company>XYZ</company>
    </Employee>
    <Employee>
      <Name>SUGRIWO</Name>
      <company>BCA</company>
    </Employee>
    <Group>40560050</Group>
    <Designation>2012-05-03</Designation>
    <Company_code>0</Company_code>
  </row>
</root>

我想输出:

A Robert Sukimin ABC 117761020 2014-03-21 5813044
B CECIL PAINEM XYZ 405600 2012-05-03 0
B SUGRIWO BCA 405600 2012-05-03 0

假设1000条记录,该xml中的循环如何循环并将数据插入到oracle表中且性能问题最小?

1 个答案:

答案 0 :(得分:3)

您可以使用多个XMLTable级别来执行此操作。一个XMLTable获取成绩,组,名称等,并将当前行作为XMLType对象。然后,第二个XMLTable从提取的行中提取所有员工姓名。

使用CTE生成基本XML:

with t (xml) as (
  select xmltype('<root>
  <row>
    <grade>A</grade>
    <Employee>
      <Name>ROBERT SUKIMIN</Name>
      <company>ABC</company>     
    </Employee>
    <Group>117761020</Group>
    <Designation>2014-03-21</Designation>
    <Company_code>5813044</Company_code>
  </row>
  <row>
    <grade>B</grade>
    <Employee>
      <Name>CECIL PAINEM</Name>
      <company>XYZ</company>
    </Employee>
    <Employee>
      <Name>SUGRIWO</Name>
      <company>BCA</company>
    </Employee>
    <Group>40560050</Group>
    <Designation>2012-05-03</Designation>
    <Company_code>0</Company_code>
  </row>
</root>') from dual
)
select x.grade, y.name, y.company, x.group_num, x.designation, x.company_code
from t
cross join xmltable ('/root/row'
  passing t.xml
  columns grade varchar2(1) path 'grade',
    row_xml xmltype path '.',
    group_num number path 'Group',
    designation varchar2(10) path 'Designation',
    company_code number path 'Company_code'
) x
cross join xmltable ('/row/Employee'
  passing x.row_xml
  columns name varchar2(30) path 'Name',
    company varchar2(5) path 'company'
) y;

得到:

G NAME                           COMPA  GROUP_NUM DESIGNATIO COMPANY_CODE
- ------------------------------ ----- ---------- ---------- ------------
A ROBERT SUKIMIN                 ABC    117761020 2014-03-21      5813044
B CECIL PAINEM                   XYZ     40560050 2012-05-03            0
B SUGRIWO                        BCA     40560050 2012-05-03            0

您可以使用insert into some_table (column1, column2, ...) select ...将该查询的结果插入到另一个表中。

通常,如果值来自表,则不需要PL / SQL来实现此目的。

如果您的XML包含在PL / SQL变量中,例如从您的Web服务调用,您可以使用该变量执行相同的操作,而不是直接从表中选择。您仍然可以直接插入目标表。在这个例子中,我假设你的本地PL / SQL变量带有web服务结果,称为l_xml,类型为XMLType;并发明了表格和列名称,因此您显然可以使用自己的真实名称:

declare
  l_xml XMLType;
  ...
begin
  -- call web service to populate l_xml
  ...

  insert into you_table(grade, name, company, group_num, designation, company_code)
  select x.grade, y.name, y.company, x.group_num, x.designation, x.company_code
  from xmltable ('/root/row'
    passing l_xml    -- your local XMLType variable
    columns grade varchar2(1) path 'grade',
      row_xml xmltype path '.',
      group_num number path 'Group',
      designation varchar2(10) path 'Designation',
      company_code number path 'Company_code'
  ) x
  cross join xmltable ('/row/Employee'
    passing x.row_xml
    columns name varchar2(30) path 'Name',
      company varchar2(5) path 'company'
  ) y;

  ...
end;

如果您要将Web服务结果检索到CLOB中,您可以将其转换为通话的一部分:

  ...
  from xmltable ('/root/row'
    passing XMLType(l_clob)    -- your local CLOB variable
  ...

您不需要使用任何循环。你可以在同一个查询中使用游标循环,并逐个将每个结果插入到你的表中,但这样做只会减慢速度而没有任何好处。