将具有重复节点的 XML 数据加载到 Oracle 中的表中
Load XML data with repeating nodes into tables in Oracle
我有以下 XML 数据(只是一个例子,真实的数据很大,我不能 post 这里)我想插入到 Oracle 11g 中的 table :
<?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, etc. " 发送给专栏作者?
我的代码如下:
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;
您可以使用 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
如@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
但是对于存储,我不确定在单个列值中使用 comma-delimited 字符串是否真的有意义;例如,这使得按特定顺序搜索书籍变得更加困难。您可以使用第二个 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
然后使用外键将作者放入单独的 table。您显示的数据实际上并没有办法唯一地标识一本书或一位作者(您可以有两本书同名 - 如果您有 ISBN 可能会有所帮助;或者两位同名的作者,并且你没有任何方法来区分它们),所以事实上这对于你正在做的事情来说可能是不可能的,但是如果你的真实数据至少可以以某种方式唯一地识别一本书那么你真的应该看看 child table 容纳所有作者。
一旦你有了它,你仍然可以使用 listagg()
生成 comma-delimited 字符串来显示,甚至直接从原始 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
(虽然这只是一种更长且可能效率较低的方法 string-join;但可以在不理解 XPath 2.0 的早期版本的 Oracle 中工作)。
我有以下 XML 数据(只是一个例子,真实的数据很大,我不能 post 这里)我想插入到 Oracle 11g 中的 table :
<?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, etc. " 发送给专栏作者?
我的代码如下:
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;
您可以使用 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
如@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
但是对于存储,我不确定在单个列值中使用 comma-delimited 字符串是否真的有意义;例如,这使得按特定顺序搜索书籍变得更加困难。您可以使用第二个 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
然后使用外键将作者放入单独的 table。您显示的数据实际上并没有办法唯一地标识一本书或一位作者(您可以有两本书同名 - 如果您有 ISBN 可能会有所帮助;或者两位同名的作者,并且你没有任何方法来区分它们),所以事实上这对于你正在做的事情来说可能是不可能的,但是如果你的真实数据至少可以以某种方式唯一地识别一本书那么你真的应该看看 child table 容纳所有作者。
一旦你有了它,你仍然可以使用 listagg()
生成 comma-delimited 字符串来显示,甚至直接从原始 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
(虽然这只是一种更长且可能效率较低的方法 string-join;但可以在不理解 XPath 2.0 的早期版本的 Oracle 中工作)。