#sql #xml #postgresql #postgresql-9.5
#sql #xml #postgresql #postgresql-9.5
Вопрос:
У меня есть XML, который необходимо вставить в таблицу. XML выглядит примерно так
<?xml version="1.0" encoding="UTF-8"?>
<root>
<pats>
<pat>
<id>1</id>
<pat_maps>
<pat_map>
<pgid>100</pgid>
<pgname>test</pgname>
</pat_map>
<pat_map>
<pgid>101</pgid>
<pgname>test1</pgname>
</pat_map>
</pat_maps>
</pat>
<pat>
<id>2</id>
<pat_maps>
<pat_map>
<pgid>102</pgid>
<pgname>test2</pgname>
</pat_map>
</pat_maps>
</pat>
<pat>
<id>3</id>
<pat_maps>
<pat_map>
<pgid>104</pgid>
<pgname>test6</pgname>
</pat_map>
<pat_map>
<pgid>105</pgid>
<pgname>test7</pgname>
</pat_map>
</pat_maps>
</pat>
</pats>
</root>
Я хочу вставить данные следующим образом
ID pgid pgname
1 100 test
1 101 test1
2 102 test2
3 104 test6
3 105 test7
Попробовал ниже, но он применяет перекрестное соединение
with x(t) as (select '<?xml version="1.0" encoding="UTF-8"?>
<root>
<pats>
..............
..........
</pat>
</pats>
</root>'::xml AS t
)
, base_id as (SELECT
unnest(xpath('/root/pats/pat/id/text()', t)) AS id
from x
), nested_rec as ( select
unnest(xpath('pgid/text()', cat_assn_list)) AS pgid,
unnest(xpath('pgname/text()', cat_assn_list)) AS pgname
from (select unnest(xpath('/root/pats/pat/pat_maps/pat_map', t)) cat_assn_list from x) q
)
select base_id.*,nested_rec.* from base_id,nested_rec;
******* output *********
ID PGID PGNAME
"1" "100" "test"
"1" "101" "test1"
"1" "102" "test2"
"1" "104" "test6"
"1" "105" "test7"
"2" "100" "test"
"2" "101" "test1"
"2" "102" "test2"
"2" "104" "test6"
"2" "105" "test7"
"3" "100" "test"
"3" "101" "test1"
"3" "102" "test2"
"3" "104" "test6"
"3" "105" "test7"
Я не нашел способа, как вложить идентификатор XML и подготовить результирующий набор?.
Есть ли какой-либо другой способ преобразовать данные xml в таблицу без использования функции XPath в PostgreSQL?
Заранее спасибо.
Комментарии:
1. XPATH — это правильный путь, но я не понимаю вашей проблемы. Что вы подразумеваете под «вложением XML» или «подготовкой результирующего набора»? Почему бы вам просто не вставить свой результат?
2. @LaurenzAlbe «вложите идентификатор XML и подготовьте результирующий набор» означает итерацию элемента ID в xml и подготовку данных подэлементов PGID и PGNAME. Можете ли вы проверить этот раздел «Я хочу вставить данные следующим образом» в описании, как мне нужен конечный результат
Ответ №1:
Следующее делает то, что вы хотите, и немного короче:
select (xpath('/pat/id/text()', d.pat))[1]::text::int as id,
(xpath('/pat_map/pgid/text()', m.map))[1]::text::int as pgid,
(xpath('/pat_map/pgname/text()', m.map))[1]::text as pgname
from x
cross join unnest(xpath('/root/pats/pat', x.t)) as d(pat)
cross join unnest(xpath('/pat/pat_maps/pat_map', d.pat)) as m(map)
;
В более современной версии Postgres вы могли бы использовать xmltable()
:
select d.*
from x
cross join xmltable ('/root/pats/pat/pat_maps/pat_map'
passing t
columns
id integer path '../../id',
pgid integer path 'pgid',
pgname text path 'pgname') as d
Комментарии:
1. Спасибо, но он не работает в версии Postgres 9.5. dbfiddle.uk /…
2. @Mahesh: ah, 9.5 требует абсолютного пути. Смотрите мое редактирование