Oracle从xmltype中提取值

时间:2013-07-09 09:24:29

标签: oracle plsql extract xmltype

这是我目前使用的代码:

SET serveroutput ON
CREATE OR REPLACE
PROCEDURE test_proc(i_xml varchar2)
IS

l_name VARCHAR2(20);
l_age NUMBER;
l_xml xmltype;
BEGIN
l_xml := xmltype(i_xml);


FOR x IN
(SELECT VALUE(p) col_val
FROM TABLE(XMLSEQUENCE(EXTRACT(l_xml, '/ROWSET/ROW'))) p
)
LOOP

     IF x.col_val.existSNode('/ROW/name/text()') > 0 THEN
          l_name:= x.col_val.EXTRACT('/ROW/name/text()').getstringVal();
     END IF;
     IF x.col_val.existSNode('/ROW/age/text()') > 0 THEN
          l_age := x.col_val.EXTRACT('/ROW/age/text()').getstringVal();
     END IF;
end loop;

end;
/
BEGIN
test_proc('<ROWSET>
<ROW>
<name>aa</name>
<age>20</age>
</ROW>
<ROW>
<name>bbb</name>
<age>25</age>
</ROW>
</ROWSET>');
END;
/

上面的代码使用xml来提取现有节点值并将其保存到特定的局部变量。它已被用于多组数据的情况下,并且工作正常。我只想知道是否可以在没有“for x loop”的情况下使用相同的内容,因为从现在开始我只会在i_xml中有一个数据,而且我只会有 nameage代码。

以下代码应该用于保存到l_name或l_age而不使用上面使用的“loop”方法:

<ROWSET>
<ROW>
    <name>aa</name>
</ROW>
</ROWSET>

<ROWSET>
<ROW>
    <age>18</age>
</ROW>
</ROWSET>

/ 我尝试使用以下内容:

SELECT
     CASE
          WHEN VALUE(p).existsNode('/ROW/name/text()') = 1
          THEN p.EXTRACT('/ROW/name/text()').getstringVal()
          WHEN VALUE(P).existsNode('/ROW/age/text()') = 1
          THEN p.EXTRACT('/ROW/age/text()').getstringVal()
     END
INTO l_new
FROM TABLE(xmlsequence(EXTRACT(l_xml, '/ROWSET/ROW'))) p;

/ 任何更好的方式表示赞赏..谢谢

1 个答案:

答案 0 :(得分:4)

如果您确定只有一个ROW,那么您可以这样做:

begin
  l_xml := xmltype(i_xml);
  if l_xml.existsnode('/ROWSET/ROW/name') > 0 then
    l_name := l_xml.extract('/ROWSET/ROW/name/text()').getstringval();
  end if;
  if l_xml.existsnode('/ROWSET/ROW/age') > 0 then
    l_age := l_xml.extract('/ROWSET/ROW/age/text()').getnumberval();
  end if;
end;

如果您有nameage,或两者都有,或者两者都没有(其中'work'表示至少没有错误),那将会有效。如果您确实有多行,则会连接结果,因此对于原始数据,l_name将为aabbbl_age将为2025。这可能不是你所期望的。