В Oracle как извлечь значения из поля XML / CLOB с несколькими значениями? - PullRequest
1 голос
/ 04 февраля 2020

Я пытаюсь использовать функцию Oracle EXTRACTVALUE () вместе с xmltype () для извлечения значений полей из типа данных CLOB. Моя проблема в том, что в нескольких строках есть несколько значений, и я не уверен, как заставить EXTRACTVALUE () работать с ними. В приведенном ниже примере есть два случая - синтаксис работает правильно в первой строке, но не во второй строке (я получаю сообщение об ошибке разбора, потому что есть несколько полей / значений). Я хотел бы просто взять самый последний (последний) набор значений в тех случаях, когда существует несколько значений.

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

1 Ответ

2 голосов
/ 04 февраля 2020

Ну, одна проблема в том, что ваши строки недопустимы XML - им нужен один root узел, содержащий остальную часть строки. Неважно, какое имя вы даете узлу root. Я не уверен, какая у вас версия Oracle, но в 12 c xmltype() произойдет сбой с LPX-00245: extra data after end of document, если нет узла root.

Тем не менее, все, что вам нужно изменить XPath, например, на /raceHistory[last()]/raceDate, чтобы получить последнюю запись raceHistory.

Вот пример, где я добавил root узел к вашему 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;

Примечание что это не получит запись raceHistory с последним raceDate - это было бы более сложно. Он просто получает последнюю запись raceHistory в строке. В вашем случае они уже отсортированы таким образом; Я просто хотел уточнить это.

...