#sql #xml #oracle #xml-parsing
Вопрос:
Я новичок в формате xml и sql, и у меня есть проблема. У меня есть SQL-запрос, который возвращает xml, как показано ниже:
<?xml version="1.0" encoding="WINDOWS-1250"?>
<AROUND>
<AB>
<Connected>1</Connected>
<EF>1010</EF>
<GH>10162</GH>
<IJ>HG-131120CXD</IJ>
<KL>New</KL>
<MN>284822</MN>
</AB>
<AB>
<Connected>0</Connected>
<EF>2123</EF>
<GH>54321</GH>
<IJ>HG-131120BRE</IJ>
<KL>Old</KL>
<MN>284822</MN>
</AB>
<AB>
<Connected>1</Connected>
<EF>4321</EF>
<GH>12345</GH>
<IJ>HG-131120DYX</IJ>
<KL>New</KL>
<MN>284822</MN>
</AB>
</AROUND>
и я должен извлечь из него некоторые значения (например: Connected, GH, IJ, KL) с помощью запроса, чтобы каждая его часть AB, независимо от того, сколько их там (в этом примере их 3, но может быть 1-10 или даже больше), имела свою собственную строку. Например (Подключен, GH, IJ, KL), первая строка будет: 1 10162 HG-131120CXD Новый. И так далее, и так далее…Заранее спасибо.
Комментарии:
1. Вы действительно имеете в виду PL/SQL или просто SQL с оракулом? PL/SQL-это процедурное расширение .
2. SQL , мой плохой, я нуб, сри за это
Ответ №1:
Вы можете использовать XMLTable() для извлечения нужных данных из вашего XML-документа; что-то вроде:
select x.connected, x.gh, x.ij, x.kl
from your_query q
cross apply xmltable (
'/AROUND/AB'
passing q.xml_doc
columns
connected number path 'Connected',
gh number path 'GH',
ij varchar2(20) path 'IJ',
kl varchar2(10) path 'KL'
) x
где your_query
находится любой запрос, который в данный момент генерирует ваш XML-документ. Если он генерирует строковое значение, вы можете обернуть его, XMLType()
чтобы преобразовать.
db<>fiddle<> показывает и то, и другое, используя CTE для представления существующего запроса для создания XML-документа или строкового значения, чтобы получить:
CONNECTED | GH | IJ | KL
--------: | ----: | :----------- | :--
1 | 10162 | HG-131120CXD | New
0 | 54321 | HG-131120BRE | Old
1 | 12345 | HG-131120DYX | New
Вы можете использовать эту инструкцию SQL в блоке PL/SQL, как и любой другой SQL; если XML-документ находится в переменной, вы можете сделать что-то вроде:
for r in (
select x.connected, x.gh, x.ij, x.kl
from xmltable (
'/AROUND/AB'
passing l_xml_doc -- local XMLType variable
columns
connected number path 'Connected',
gh number path 'GH',
ij varchar2(20) path 'IJ',
kl varchar2(10) path 'KL'
) x
) loop
-- do something with r.connected, r.gh etc.
end loop;
Ответ №2:
Вы можете использовать два выражения XPath с общими табличными выражениями. С помощью первого вы разделяете AB
узлы, а со вторым объединяете соответствующие элементы в строку.
with tmp as (
select unnest (xpath ('//AB',
'<?xml version="1.0" encoding="WINDOWS-1250"?>
<AROUND>
<AB>
<Connected>1</Connected>
<EF>1010</EF>
<GH>10162</GH>
<IJ>HG-131120CXD</IJ>
<KL>New</KL>
<MN>284822</MN>
</AB>
<AB>
<Connected>0</Connected>
<EF>2123</EF>
<GH>54321</GH>
<IJ>HG-131120BRE</IJ>
<KL>Old</KL>
<MN>284822</MN>
</AB>
<AB>
<Connected>1</Connected>
<EF>4321</EF>
<GH>12345</GH>
<IJ>HG-131120DYX</IJ>
<KL>New</KL>
<MN>284822</MN>
</AB>
</AROUND>')) ab
)
select unnest (xpath ('concat(//Connected/text()," ",//GH/text()," ",//IJ/text()," ",//KL/text())', tmp.ab)) ab
from tmp;
Это возвращает:
ab
--------------------------
1 10162 HG-131120CXD New
0 54321 HG-131120BRE Old
1 12345 HG-131120DYX New
Комментарии:
1. Вопрос помечен для Oracle, а не для PostgreSQL, поэтому этот синтаксис не будет работать для OP.
2. @Alexpool Действительно, я скучал по этому.