在 Oracle 中,如何从具有多个值的 XML/CLOB 字段中提取值?

In Oracle, how to extract values from XML/CLOB field that has multiple values?

我正在尝试使用 Oracle 函数 EXTRACTVALUE() 和 xmltype() 从 CLOB 数据类型中提取字段值。我的问题是因为某些行中有多个值,我不确定如何让 EXTRACTVALUE() 处理这些值。在下面的示例中,有两种情况——语法在第一行正确工作,但在第二行不正确(我收到一条解析失败消息,因为有多个 fields/values)。在存在多个值的情况下,我只想采用最新(最后)的一组值。

create table TEST1 
(
  id1         numeric(2),
  col1        CLOB not null  
);

-- Insert data:
INSERT INTO TEST1 (id1, col1) values (1, '<raceHistory><raceDate>1980-05-26</raceDate><raceType>CLASSIC</raceType></raceHistory>');
INSERT INTO TEST1 (id1, col1) values (2, '<raceHistory><raceDate>1997-06-21</raceDate><raceType>MARATHON</raceType></raceHistory><raceHistory><raceDate>2017-01-01</raceDate><raceType>SKATE</raceType></raceHistory>');

-- Make sure it populated correctly.
select * from TEST1;

-- Now try to extract the field values for raceDate and raceType:
-- The parsing works fine for the first row...
SELECT 
    EXTRACTVALUE(xmltype(col1), '/raceHistory/raceDate') as raceDate,
    EXTRACTVALUE(xmltype(col1), '/raceHistory/raceType') as raceType
FROM TEST1
WHERE id1 = 1;

-- ... but the parsing fails on this one because there are multiple values:
SELECT 
    EXTRACTVALUE(xmltype(col1), '/raceHistory/raceDate') as raceDate,
    EXTRACTVALUE(xmltype(col1), '/raceHistory/raceType') as raceType
FROM TEST1
WHERE id1 = 2;

我想要的输出是这样的——对于第二行,我只想要最后一个值(即最新的利率表变量)。

id1 raceDate    raceType
1   1985-05-25  CLASSIC
2   2017-01-01  SKATE

好吧,一个问题是您的字符串无效 XML - 它们需要一个包含字符串其余部分的根节点。给根节点起什么名字并不重要。我不确定您使用的是哪个 Oracle 版本,但在 12c 中,如果没有根节点,xmltype() 将失败并显示 LPX-00245: extra data after end of document

就是说,您只需将 XPath 更改为例如/raceHistory[last()]/raceDate 获取最后一个 raceHistory 条目。

这是我向您的 xml 添加根节点的示例:

with test1 as (select 2 as id1, '<root><raceHistory><raceDate>1997-06-21</raceDate><raceType>MARATHON</raceType></raceHistory><raceHistory><raceDate>2017-01-01</raceDate><raceType>SKATE</raceType></raceHistory></root>' as col1 from dual)
SELECT 
    EXTRACTVALUE(xmltype(col1), '/root/raceHistory[last()]/raceDate') as raceDate,
    EXTRACTVALUE(xmltype(col1), '/root/raceHistory[last()]/raceType') as raceType
FROM TEST1
WHERE id1 = 2;

请注意,这不会获取具有最新 raceDate 的 raceHistory 条目——那样会更复杂。它只是获取字符串中的最后一个 raceHistory 条目。在您的情况下,它们已经按照这种方式排序;我只是想澄清一下。