XML DB简介
Oracle XML DB 是一组专门为 XML 开发的内置高性能存储和检索技术。OracleXML DB 将 World Wide Web Consortium (W3C) XML 数据模型完全吸收到 Oracle9i 数据库中,并为导航和查询 XML 提供了新的标准访问方法。可以同时获得关系数据库技术和 XML 技术的所有优势。Oracle XML DB 可用于存储、查询、更新、转换或处理 XML,并使用 SQL 查询访问相同的 XML 数据。
文章主要内容
本文主要描述了在什么地方和怎样使用Oracle XML DB。文章除了讨论了Oracle XML DB的一般使用场景下XMLType数据的存取(Storage and Acess),以及相关数据的更新(Update)和验证(Validation)而外还解释了为什么学习使用Oracle XML DB对Xpath和XML Schema的学习是有帮助作用的。文中还包括了相关的实例。通过阅读本文可以了解到如何在不同的客户端程序中使用标准的协议来对存储了XML Type数据类型的数据库进行操作。
包括的小节:
n 向XMLType或者XMLType column数据表中存放数据。
n 从XMLType或者XMLType column数据表中取数据。
n 在Oracle XML DB中使用Xpath。
n 使用updateXML()方法更新XML文档。
向XMLType或者XMLType column数据表中存放数据
当需要要向Oracle9i数据库中存储XML文档时,可以采取如下的这些方法,包括:
n 在Oracle9i数据库外部将XML文档进行解析,将分析所得到的结果以行的形式存入一个或者多个表中。在这种场景下,数据库不知道正在处理的是XML格式的内容。
n 将XML文档存储在Oracle9i数据库的CLOB或者VARCHAR2字段。这种场景下数据库仍然无法知道正在处理XML文档。但是用户可以使用XDK编写程序来执行XML操作。
n 把XML文档作为XMLType数据类型存储在Oracle9i数据库中。
使用以下两种方式都是有效的:
n 将XML文档存储在XMLType数据列中。
n 将XML文档存储在XMLType数据表中。
采用以上两种方式存储就意味着数据库能够知道正在处理的数据是XML文档,使用这种方法来存放XML文档将给我们带来很大的方便,因为Oracle9i数据库中提供了一系列的新特性,这使得对XML数据进行高效的处理变成了可能。
Example 3-1 创建一个带 XMLType 数据列的表
Example 3-2 创建一个XMLType表CREATE TABLE Example1
(
KEYVALUE varchar2( 10 ) primary key,
XMLCOLUMN xmltype
);
CREATE TABLE XMLTABLE OF XMLType;
Example 3-3将XML文档转化XMLType实例,然后存储到XMLType表或者带XMLType数据列的表中
为了将 XML文档存到XMLType数据表或者带XMLType数据列的表中首先必须将XML文档转化为XMlType实例。这个动作可以使用XMLType数据类型所提供的各种各样的构造函数来完成,例如使用一个PL/SQL函数getClobDocument():
使用方法:create or replace function getClobDocument(
filename in varchar2 ,
charset in varchar2 default NULL )
return CLOB deterministic
is
file bfile : = bfilename( ' c:/ ' ,filename);
charContent CLOB : = ' ' ;
targetFile bfile;
lang_ctx number : = DBMS_LOB.default_lang_ctx;
charset_id number : = 0 ;
src_offset number : = 1 ;
dst_offset number : = 1 ;
warning number ;
begin
if charset is not null then
charset_id : = NLS_CHARSET_ID(charset);
end if ;
targetFile : = file ;
DBMS_LOB.fileopen(targetFile, DBMS_LOB.file_readonly);
DBMS_LOB.LOADCLOBFROMFILE(charContent, targetFile,
DBMS_LOB.getLength(targetFile), src_offset, dst_offset,
charset_id, lang_ctx,warning);
DBMS_LOB.fileclose(targetFile);
return charContent;
end ;
/
-- create XMLDIR directory
-- connect system/manager
-- create directory XMLDIR as '<location_of_xmlfiles_on_server>';
-- grant read on directory xmldir to public with grant option;
-- you can use getCLOBDocument() to generate a CLOB from a file containing
-- an XML document. For example, the following statement inserts a row into the
-- XMLType table Example2 created earlier:
VALUES (XMLTYPE(getCLOBDocument( ' purchaseorder.xml ' )));
注意Charset参数的使用,它用来确定指定文件的字符集,如果该参数被忽略,将默认采用当前数据库所采用的字符集,例如在文档invoice.xml中使用的韩文字符集KO16KSC5601,它可以被装载到XMLType数据表XMLDOC数据表中:
values (xmltype(getClobDocument( ' invoice.xml ' , ' KO16KSC5601 ' )));
下面的例子将使用UTF8文件格式
values (xmltype(getClobDocument( ' invoice.xml ' , ' UTF8 ' )));
如果不使用Charset参数将默认使用ZHS16GBK.
获取XMLType表或者带有XMLType数据列的表中的数据insert into xmldoc values (xmltype(getClobDocument( ' invoice.xml ' )));
一旦一组XML文档存储为许多XMLType表或者许多XMLType数据列之后,下一步要做的就是对存储的数据进行恢复操作。当需要对一组XML文档进行操作时,通常需两个基本工作要做:
决定怎样从一组XML文档中找到需要的子集。
决定怎样更优地从一组XML文档所包含的节点集(nodes)中找到需要的子集。
由于在Oracle9i数据库和XMLType数据类型提供了许多相关的函数使得上述的这些操作变得非常简单。这些函数使用W3C的XPath推荐标准来对一组XML文档中的数据进行导航。
在Oracle XML DB中使用Xpath
XML DB中提供的许多函数都是基于W3C Xpath推荐标准的。Xpath规范规定通过使用“/”符号来访问XML文档中的的元素和属性,例如/A/B,/A@name(name表示属性名)。在XML DB中使用XPath表达式和我们比较熟悉的SQl语句能很好地完成对XML文档的相关操作。
Xpath在Oracle XML DB中的主要作用是结合extract(),extractValue(),和existsNode()等函数来完成一些数据操作。
函数existsNode()的作用是判断在给定的XML文档中是否存在一个与Xpath表达式吻合的节点。如果文档中存在这么一个节点,函数将返回值1。
PurchaseOrder XML文档
本节中的例子都是基于一下的PurchaseOrder XMl文档。
使用existNode()函数< PurchaseOrder
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation ="http://www.oracle.com/xdb/po.xsd" >
< Reference > ADAMS-20011127121040988PST </ Reference >
< Actions >
< Action >
< User > SCOTT </ User >
< Date > 2002-03-31 </ Date >
</ Action >
</ Actions >
< Reject />
< Requestor > Julie P. Adams </ Requestor >
< User > ADAMS </ User >
< CostCenter > R20 </ CostCenter >
< ShippingInstructions >
< name > Julie P. Adams </ name >
< address > Redwood Shores, CA 94065 </ address >
< telephone > 650 506 7300 </ telephone >
</ ShippingInstructions >
< SpecialInstructions > Ground </ SpecialInstructions >
< LineItems >
< LineItem ItemNumber ="1" >
< Description > The Ruling Class </ Description >
< Part Id ="715515012423" UnitPrice ="39.95" Quantity ="2" />
</ LineItem >
< LineItem ItemNumber ="2" >
< Description > Diabolique </ Description >
< Part Id ="037429135020" UnitPrice ="29.95" Quantity ="3" />
</ LineItem >
< LineItem ItemNumber ="3" >
< Description > 8 1/2 </ Description >
< Part Id ="037429135624" UnitPrice ="39.95" Quantity ="4" />
</ LineItem >
</ LineItems >
</ PurchaseOrder >
该函数的语法示意图3-1:
exitstNode()语法示意图:
Example 3-4 existsNode() 示例:寻找一个与XPath表达式匹配的节点
以PurchaseOrder XML为例, 在下面的程序中使用existsNode将返回值“1”:
SELECT existsNode(value(X), ' /PurchaseOrder/Reference ' )
FROM XMLTABLE X;
SELECT existsNode(value(X),
' /PurchaseOrder[Reference="ADAMS-20011127121040988PST"] ' )
FROM XMLTABLE X;
SELECT existsNode(value(X),
' /PurchaseOrder/LineItems/LineItem[2]/Part[@Id="037429135020"] ' )
FROM XMLTABLE X;
SELECT existsNode(value(X),
' /PurchaseOrder/LineItems/LineItem[Description="8 1/2"] ' )
FROM XMLTABLE X;
Example 3-5 existsNode() 示例:不存在与Xpath表达式匹配的节点
由于不存在与Xpath表达式相匹配的节点,existsNode将返回值0:
SELECT existsNode(value(X),'/PurchaseOrder/UserName')
FROM XMLTABLE X;
SELECT existsNode(value(X),
'/PurchaseOrder[Reference="ADAMS-XXXXXXXXXXXXXXXXXXXX"]')
FROM XMLTABLE X;
SELECT existsNode(value(X),
'/PurchaseOrder/LineItems/LineItem[3]/Part[@Id="037429135020"]')
FROM XMLTABLE X;
SELECT existsNode(value(X),
'/PurchaseOrder/LineItems/LineItem[Description="Snow White"]')
FROM XMLTABLE X;
existsNode()
函数的最普遍的用法是将其放在SELECT,UPDATE,DELETE等SQL语句的where子句中。
这种情况下,Xpath 表达式被传递给existsNode()
函数,where语句通过existsNode()函数的返回值来决定数据表中的哪一个XML文档将被
SQl语句处理。
Example 3-6 在where子句中使用existsNode()函数。
SELECT count ( * )
FROM XMLTABLE x
WHERE existsNode(value(x), ' /PurchaseOrder[User="ADAMS"] ' ) = 1 ;
DELETE FROM XMLTABLE x
WHERE existsNode(value(x), ' /PurchaseOrder[User="ADAMS"] ' ) = 1 ;
commit ;
extractNode()函数也是以Xpath表达式为参数,将返回以XMLtype数据类型存放在数据库中的XML文档中的text节点或者节点
属性值。这个返回值将以一般对象数据类型的形式返回。
该函数的语法示意图:
extractValue()
函数的使用示例
:
Example 3-7 extractValue()的有效使用示例
返回:SELECT extractValue(value(x), ' /PurchaseOrder/Reference ' )
FROM XMLTABLE X;
EXTRACTVALUE(VALUE(X),'/PURCHASEORDER/REFERENCE')
------------------------------------------------------------------------
ADAMS-20011127121040988PST
返回:SELECT extractValue(value(x),
' /PurchaseOrder/LineItems/LineItem[2]/Part/@Id ' )
FROM XMLTABLE X;
EXTRACTVALUE(VALUE(X),'/PURCHASEORDER/LINEITEMS/LINEITEM[2]/PART/@ID')
-----------------------------------------------------------------------
037429135020
extractValue()
函数只能返回某一个text节点的的值或者某一个节点的属性值. 以下是两个extractValue()函数的无效使用示例。在第一个示例中Xpath表达式
可以匹配三个XML文档中的节点,在第二个例子中Xpath表达式指向的是一个树形节点而非某个text节点的值或者某一个节点的属性值。应此可以看到,这两种用法
都是无效的使用方法。
Example 3-8 extractValue()无效使用示例
SELECT extractValue(value(X),
' /PurchaseOrder/LineItems/LineItem/Description ' )
FROM XMLTABLE X;
-- FROM XMLTABLE X;
-- *
-- ERROR at line 3:
-- ORA-19025: EXTRACTVALUE returns value of only one node
SELECT extractValue(value(X),
' /PurchaseOrder/LineItems/LineItem[1] ' )
FROM XMLTABLE X;
-- FROM XMLTABLE X
-- *
-- ERROR at line 3:
-- ORA-19025: EXTRACTVALUE returns value of only one node
Example 3-9将extractValue() 使用在where子句中
extractValue()
也可以被放置在 SELECT
, UPDATE
, 或者 DELETE
等SQL语句的where子句中. 这使得我们可以实现XMLType表之间的联接、
带有XMLType数据列的表之间的联接、和其他的关系型数据表与XMLType之间的联接。以下的查询展示了怎样在SELECT清单中和where子句中使用extractValue()方法。
SELECT
extractValue(value(x),
'
/PurchaseOrder/Reference
'
)
FROM
XMLTABLE X, SCOTT.EMP
WHERE
extractValue(value(x),
'
/PurchaseOrder/User
'
)
=
EMP.ENAME
AND
EMP.EMPNO
=
7876
;
--返回:
-- EXTRACTVALUE(VALUE(X),'/PURCHASEORDER/REFERENCE')
-- --------------------------------------------------
使用extract()函数
语法示意图3-3:
extract()
函数用来获取Xpath指向的一组节点。
这些节点将以XMLType实例的形式返回。extract()
函数的返回值既可以是一个XML文档也可以是XML文档片断。
Example 3-10 使用 extract() 返回XML文档片断
下面的程序使用extract()
函数返回XMLType
实例。
该实例是一个包含了Xpath所指向的一组Description节点.
-- 返回:set long 20000
SELECT extract(value(X),
' /PurchaseOrder/LineItems/LineItem/Description ' )
FROM XMLTABLE X;
-- EXTRACT(VALUE(X),'/PURCHASEORDER/LINEITEMS/LINEITEM/DESCRIPTION')
-- ------------------------------------------------------------------
-- <Description>The Ruling Class</Description>
-- <Description>Diabolique</Description>
-- <Description>8 1/2</Description>
Example 3-11用 extract() 函数返回 一棵 XPath 表达式指向的节点树
返回:SELECT extract(value(X),
' /PurchaseOrder/LineItems/LineItem[1] ' )
FROM XMLTABLE X;
EXTRACT(VALUE(X),'/PURCHASEORDER/LINEITEMS/LINEITEM[1]')
-------------------------------------------------------------------------
<
LineItem
ItemNumber
="1"
>
<
Description
>
The Ruling Class
</
Description
>
<
Part
Id
="715515012423"
UnitPrice
="39.95"
Quantity
="2"
/>
</
LineItem
>
使用XMLSequence()函数
XMLSequence语法示意图:
XMLSequence()
函数可以将XML文档片断转化为一系列的XMLType实例。XMLSequence()函数可以通过获取一个包含XML文档片段的XMLType实例来
返回
组
XMLType
对象。 这一组对象的中的每一个对象对应一个XML文档片断中的一个根级的节点。 最后,使用SQL TABLE()函数就可以将这一组对象转化为数据
行集合。
Example 3-12 使用XMLSequence() 和 TABLE()函数从XML文档中提取Description 的节点值
set long 10000
set feedback on
SELECT extractValue(value(t), ' /Description ' )
FROM XMLTABLE X,
TABLE ( xmlsequence (
extract(value(X),
' /PurchaseOrder/LineItems/LineItem/Description ' )
)
) t;
返回:
EXTRACTVALUE(VALUE(T),'/DESCRIPTION')
-------------------------------------------------------------------------
The Ruling Class
Diabolique
8 1/2
使用updateXML()方法来更新XML文档
语法示意图3-5:
updateXML() 函数可以用来对XML文档中的节点的属性值,节点,text节点值,树形节点进行更新。更新的对象的位置由Xpath表达式来指定。
以下的程序展示了如何对以XMLType形式存放在数据表中的XML文档进行更新操作。
Example 3-13使用 updateXML()方法来对XPath表达式所指定的Text节点 的值进行更新
XPath表达式为`/PurchaseOrder/Reference':
SET value(t) = updateXML(value(t),
' /PurchaseOrder/Reference/text() ' ,
' MILLER-200203311200000000PST ' )
WHERE existsNode(value(t),
' /PurchaseOrder[Reference="ADAMS-20011127121040988PST"] ' ) = 1 ;
返回:
FROM XMLTABLE t;
-------------------------------------------------------------------------
<Reference>MILLER-200203311200000000PST</Reference>
</PurchaseOrder>
Example 3-14 使用 updateXML() 函数来替代Xath表达式所指定的树形节点
XPath 表达式: `/PurchaseOrders/LineItems/LineItem[2]'.
SET value(t) =
updateXML(value(t),
' /PurchaseOrder/LineItems/LineItem[2] ' ,
xmltype( ' <LineItem ItemNumber="4">
<Description>Andrei Rublev</Description>
<Part Id="715515009928" UnitPrice="39.95"
Quantity="2"/>
</LineItem> '
)
)
WHERE existsNode(value(t),
' /PurchaseOrder[Reference="MILLER-200203311200000000PST"] '
) = 1 ;
返回:
FROM XMLTABLE t;
返回:
------------------------------------------------------------------------
paceSchemaLocation="http://www.oracle.com/xdb/po.xsd">
<Reference>MILLER-200203311200000000PST</Reference>
<LineItems>
<LineItem ItemNumber="1">
<Description>The Ruling Class</Description>
<Part Id="715515012423" UnitPrice="39.95" Quantity="2"/>
</LineItem>
<LineItem ItemNumber="4">
<Description>Andrei Rublev</Description>
<Part Id="715515009928" UnitPrice="39.95" Quantity="2"/>
</LineItem>
<LineItem ItemNumber="3">
<Description>8 1/2</Description>
<Part Id="037429135624" UnitPrice="39.95" Quantity="4"/>
</LineItem>
</LineItems>
</PurchaseOrder>
(原文:Oracle9i XML Database Developer’s Guide - Oracle XML DB release 2)