Oracle XML DB 的使用

Oracle XML DB 的使用

 

 

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 DBXpathXML 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 数据列的表


   
    
    
CREATE TABLE Example1
(
    KEYVALUE  varchar2( 10 )  primary key,
    XMLCOLUMN xmltype
);   
Example 3-2
创建一个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:
使用方法:

INSERT   INTO  XMLTABLE 
VALUES (XMLTYPE(getCLOBDocument( ' purchaseorder.xml ' )));

注意Charset参数的使用,它用来确定指定文件的字符集,如果该参数被忽略,将默认采用当前数据库所采用的字符集,例如在文档invoice.xml中使用的韩文字符集KO16KSC5601,它可以被装载到XMLType数据表XMLDOC数据表中:

insert   into  xmldoc
    values (xmltype(getClobDocument( ' invoice.xml ' , ' KO16KSC5601 ' )));

下面的例子将使用UTF8文件格式

insert   into  xmldoc
    values (xmltype(getClobDocument( ' invoice.xml ' , ' UTF8 ' )));

如果不使用Charset参数将默认使用ZHS16GBK.


   
   
   
insert   into  xmldoc  values (xmltype(getClobDocument( ' invoice.xml ' )));
获取XMLType表或者带有XMLType数据列的表中的数据

一旦一组XML文档存储为许多XMLType表或者许多XMLType数据列之后,下一步要做的就是对存储的数据进行恢复操作。当需要对一组XML文档进行操作时,通常需两个基本工作要做:

决定怎样从一组XML文档中找到需要的子集。

决定怎样更优地从一组XML文档所包含的节点集(nodes)中找到需要的子集。

由于在Oracle9i数据库和XMLType数据类型提供了许多相关的函数使得上述的这些操作变得非常简单。这些函数使用W3CXPath推荐标准来对一组XML文档中的数据进行导航。

Oracle XML DB中使用Xpath

XML DB中提供的许多函数都是基于W3C Xpath推荐标准的。Xpath规范规定通过使用“/”符号来访问XML文档中的的元素和属性,例如/A/B,/A@name(name表示属性名)。在XML DB中使用XPath表达式和我们比较熟悉的SQl语句能很好地完成对XML文档的相关操作。

XpathOracle XML DB中的主要作用是结合extract(),extractValue(),existsNode()等函数来完成一些数据操作。

函数existsNode()的作用是判断在给定的XML文档中是否存在一个与Xpath表达式吻合的节点。如果文档中存在这么一个节点,函数将返回值1

PurchaseOrder XML文档

本节中的例子都是基于一下的PurchaseOrder XMl文档。


   
   
   
< 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 >
使用existNode()函数

该函数的语法示意图31

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()函数的最普遍的用法是将其放在SELECTUPDATE,DELETESQL语句的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-9extractValue() 使用在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')
-- --------------------------------------------------

-- ADAMS-20011127121040988PST  

使用extract()函数

语法示意图33

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文档
语法示意图35

updateXML() 函数可以用来对XML文档中的节点的属性值,节点,text节点值,树形节点进行更新。更新的对象的位置由Xpath表达式来指定。

以下的程序展示了如何对以XMLType形式存放在数据表中的XML文档进行更新操作。

Example 3-13使用 updateXML()方法来对XPath表达式所指定的Text节点 的值进行更新

XPath表达式为`/PurchaseOrder/Reference':

 

UPDATE  XMLTABLE t
     SET  value(t)  =  updateXML(value(t),
                            ' /PurchaseOrder/Reference/text() ' ,
                            ' MILLER-200203311200000000PST ' )
     WHERE  existsNode(value(t),
        ' /PurchaseOrder[Reference="ADAMS-20011127121040988PST"] ' )  =   1 ;

返回:

1 row updated.

SELECT  value(t)
   FROM XMLTABLE t;

 

This returns:

VALUE(T)

-------------------------------------------------------------------------

<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:noNamespaceSchemaLocation="http://www.oracle.com/xdb/po.xsd">
   <Reference>MILLER-200203311200000000PST</Reference>

</PurchaseOrder>  

 

Example 3-14 使用 updateXML() 函数来替代Xath表达式所指定的树形节点

XPath 表达式: `/PurchaseOrders/LineItems/LineItem[2]'.

 

UPDATE  XMLTABLE t
   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 ;

返回:

1 row updated.

 

SELECT  value(t)
   FROM  XMLTABLE t;

返回:

VALUE(T)

------------------------------------------------------------------------

<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:noNames

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>  

猜你喜欢

转载自blog.csdn.net/wangshengfeng1986211/article/details/6559283