我有以下XML数据(只是一个例子,真正的一个很大,我不能在这里发布),我想在Oracle 11g中插入一个表:
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="WEB">
<title lang="en">XQuery Kick Start</title>
<author>James McGovern</author>
<author>Per Bothner</author>
<author>Kurt Cagle</author>
<author>James Linn</author>
<author>Vaidyanathan Nagarajan</author>
<year>2003</year>
<price>49.99</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
这里,我在一个节点内重复了几次元素<author>
。我如何编写我的XQuery以获得结果“James McGovern,Per Bothner,Kurt Cagle,James Linn等”进入专栏作者?
我的代码如下:
SELECT x1.*
FROM test_xml t,
XMLTABLE(XMLNAMESPACES(DEFAULT 'http://www.loc.gov/MARC21/slim'), '/bookstore/book'
PASSING t.OBJECT_VALUE COLUMNS category VARCHAR2(100) PATH '@category',
title VARCHAR2(100) PATH 'title',
author VARCHAR2(100) PATH 'author',
year VARCHAR2(100) PATH 'year',
price VARCHAR2(100) PATH 'price'
) x1;
答案 0 :(得分:1)
您可以使用XMLQuery和字符串连接功能(XPath 2.0)。
create table test(xml xmltype);
select xmlcast(
xmlquery(('string-join(//book/author/child::text(),",")' )
passing xml returning content) as varchar2(256)) as result
from test;
result
1 Giada De Laurentiis,J K. Rowling,James McGovern,Per Bothner,Kurt Cagle,James Linn,Vaidyanathan Nagarajan,Erik T. Ray
答案 1 :(得分:1)
正如@are所示,您可以使用[string-join()
](http://www.w3.org/TR/xpath-functions/#func-string-join),但可能您希望作者与每本书相关联,您可以通过坚持使用XMLTable获得 - 您可能已经适应了这一点你自己回答:
select x.*
from test_xml t
cross join xmltable('/bookstore/book'
passing t.object_value
columns title varchar2(30) path 'title',
category varchar2(10) path '@category',
year number(4) path 'year',
price number path 'price',
authors varchar2(100) path 'string-join(author/child::text(),",")'
) x;
TITLE CATEGORY YEAR PRICE AUTHORS
------------------------------ ---------- ---------- ---------- ----------------------------------------------------------------------------------------------------
Everyday Italian COOKING 2005 30 Giada De Laurentiis
Harry Potter CHILDREN 2005 29.99 J K. Rowling
XQuery Kick Start WEB 2003 49.99 James McGovern,Per Bothner,Kurt Cagle,James Linn,Vaidyanathan Nagarajan
Learning XML WEB 2003 39.95 Erik T. Ray
但是对于存储,我不确定在单个列值中使用逗号分隔的字符串是否真的有意义;例如,它使得按特定订单搜索书籍变得更加困难。您可以使用第二个XMLTable更加关联地提取数据:
select x.title, x.category, x.year, x.price, y.author
from test_xml t
cross join xmltable('/bookstore/book'
passing t.object_value
columns title varchar2(30) path 'title',
category varchar2(10) path '@category',
year number(4) path 'year',
price number path 'price',
authors xmltype path './author'
) x
cross join xmltable('/author'
passing x.authors
columns author varchar2(30) path '.'
) y;
TITLE CATEGORY YEAR PRICE AUTHOR
------------------------------ ---------- ---------- ---------- ------------------------------
Everyday Italian COOKING 2005 30 Giada De Laurentiis
Harry Potter CHILDREN 2005 29.99 J K. Rowling
XQuery Kick Start WEB 2003 49.99 James McGovern
XQuery Kick Start WEB 2003 49.99 Per Bothner
XQuery Kick Start WEB 2003 49.99 Kurt Cagle
XQuery Kick Start WEB 2003 49.99 James Linn
XQuery Kick Start WEB 2003 49.99 Vaidyanathan Nagarajan
Learning XML WEB 2003 39.95 Erik T. Ray
然后使用外键将作者放入单独的表中。您显示的数据并不能真正找到唯一标识书籍或作者的方法(您可以拥有两本具有相同标题的书籍 - 如果您拥有可能有用的ISBN;或者两位作者相同的名称,你没有任何方法可以区分它们),所以事实上你可能无法做到这一点,但如果你真实的数据至少可以以某种方式唯一地识别一本书然后你应该真正看一张儿童桌来容纳所有作者。
一旦你有了这个,你仍然可以使用listagg()
生成逗号分隔的字符串以供显示,甚至可以直接从原始XML作为演示:
select x.title, x.category, x.year, x.price,
listagg(y.author, ',') within group (order by y.author) as authors
from test_xml t
cross join xmltable('/bookstore/book'
passing t.object_value
columns title varchar2(30) path 'title',
category varchar2(10) path '@category',
authors xmltype path './author',
year number(4) path 'year',
price number path 'price'
) x
cross join xmltable('/author'
passing x.authors
columns author varchar2(20) path '.'
) y
group by x.title, x.category, x.year, x.price;
TITLE CATEGORY YEAR PRICE AUTHORS
------------------------------ ---------- ---------- ---------- ----------------------------------------------------------------------------------------------------
Harry Potter CHILDREN 2005 29.99 J K. Rowling
Learning XML WEB 2003 39.95 Erik T. Ray
Everyday Italian COOKING 2005 30 Giada De Laurentiis
XQuery Kick Start WEB 2003 49.99 James Linn,James McGovern,Kurt Cagle,Per Bothner,Vaidyanathan Nagaraj
(虽然这只是一种更长且可能效率更低的字符串连接方式;但是在早期版本的Oracle中无法理解XPath 2.0)。