构建和转换XML,Oracle编程入门经典

Oracle 9i产品帮助文档:

在 Oracle 数据库 10g 第 2 版中,Oracle
引入了一个与该数据库集成的专职能自带 XQuery
引擎,该引擎可用以达成与支出协理 XML 的应用程序相关的各个职务。XQuery
是一种用于拍卖 XML 数据模型的询问语言,它实际可操作任何类型的可用 XML
表明的数目。固然 Oracle XQuery
实施使您能够运用数据库数据和表面数据源,但在拍卖数据库中贮存的结构化数据方面,Oracle
XML DB 平日可以明确提升性能。

http://docs.oracle.com/cd/B10501_01/index.htm

本文提供的言传身教不仅示范了在怎么着场所下以及哪些运用 XQuery 查询、构建和更换
XML,而且还以身作则了怎么着监控和剖析 XQuery
表达式的性能执行,从而找到更高效的方法来处理同一工作负荷。

可依据自己索要举行查询,包涵了好多的文档。

根据关周全据构建 XML

 

在要求的状态下(例如,向 Web 服务发送结果),您可能要基于关全面据构建
XML。要在 Oracle 数据库 10g 第 2
版往日的本子中成就此任务,平常必要动用 SQL/XML 生成函数,如
XMLElement、XMLForest 和 XMLAgg()。在 Oracle 数据库 10 g 第 2
版中,XQuery 将比那一个函数更为急忙。具体而言,在 XQuery 表明式内部选用ora:view XQuery 函数,您可以查询现有的涉及表或视图以及立刻构建
XML,从而不必经过关全面据显式创设 XML 视图。列表 1 中的 PL/SQL
代码演示了怎么拔取 ora:view 基于示例数据库格局 HR
的默许员工涉嫌表中蕴藏的数额构建 XML 文档。

Sample Schemas的目录:

列表 1:使用 ora:view 基于关周密据成立 XML

http://docs.oracle.com/cd/B10501_01/server.920/a96539/toc.htm

BEGIN
IF(DBMS_XDB.CREATEFOLDER('/public/employees')) THEN
DBMS_OUTPUT.PUT_LINE('Folder is created');
ELSE
DBMS_OUTPUT.PUT_LINE('Cannot create folder');
END IF;
COMMIT;
END;
/
DECLARE
XMLdoc XMLType;
BEGIN
SELECT XMLQuery(
'for $j in 1
return (
{
for $i in ora:view("HR", "employees")/ROW
where $i/EMPLOYEE_ID <= 102
return (
{xs:string($i/EMPLOYEE_ID)}
{xs:string($i/LAST_NAME)}
{xs:integer($i/SALARY)}
)} )'
RETURNING CONTENT) INTO XMLdoc FROM DUAL;
IF(DBMS_XDB.CREATERESOURCE('/public/employees/employees.xml', XMLdoc)) THEN
DBMS_OUTPUT.PUT_LINE('Resource is created');
ELSE
DBMS_OUTPUT.PUT_LINE('Cannot create resource');
END IF;
COMMIT;
END;
/

 

在列表 1 中的第二个 PL/SQL 进程中,您只是在 XML
音讯库中开创了一个新文件夹。在该音讯库文件夹中,您随后将积存此处突显的第二个PL/SQL 进程中开创的 XML 文档。第一个 PL/SQL 进度首头阵出 SELECT
语句,该语句使用 XMLQuery SQL 函数基于关周全据构建 XML。对于 XQuery
表达式(XMLQuery 在此间将其当作参数)而言,请小心嵌套的 FLWOR
表达式中利用的 ora:view XQuery 函数。在该示例中,ora:view
获取七个输入参数,即“HR”和“employees”,它们提示该函数查询属于 HR
数据库格局的员工表。由此,ora:view 将回来一个代表 HR.employees
表行的职工 XML
文档体系。但为了节省结果文档中的空间,只将前多个职工记录传递给结果种类。那是通过在
FLWOR 表明式的 where 子句中指定 $i/EMPLOYEE_ID <= 102
而完成的。请小心 FLWOR 表达式的 return 子句中使用的 xs:string()
xs:integer() XQuery 类型表明式。实际上,此处使用的这几个 XQuery
表达式不仅将 XML
节点值转换为对应的品类,而且还将提取那一个节点值。随后,生成的员工 XML
文档作为 employees.xml 保存到前面在列表 1 中另一个 PL/SQL 进程中开创的
/public/employees XML 消息库文件夹。要保证此操作已到位,可举办以下查询:

萨姆ple Schemas的文档(示例情势的表及介绍):

SELECT XMLQuery('for $i in fn:doc("/public/employees/employees.xml")
return;
$i'
RETURNING CONTENT) AS RESULT FROM DUAL;

http://docs.oracle.com/cd/B10501_01/server.920/a96539.pdf

该查询应生成以下输出:

 


100
King
24000


101
Kochhar
17000


102
De Haan
17000

重重年来,Oracle助教、管理员、程序员、以及用户为了学习、测试或调整他们的数据库,都从来在行使那一个值得依靠的SCOTT方式开展着不难地询问、更新、以及去除操作。那几个情势就是大家所说的示范情势。示例形式是表、视图、索引那样的数据库对象的集结,并且随着预先供了代表小圈圈依旧中等规模集团的数据。

在上述 XQuery 中,fn:doc XQuery 函数用于访问 Oracle XML DB
音信库中存储的单个 XML 文档。但倘使要处理局地享有同等或一般结构的 XML
文档(存储在同一 XML
音信库文件夹中),应该如何是好?那种场地下,另一个用来拍卖 XML
音讯库资源的 XQuery 函数(即
fn:collection)可能会派上用场。本文稍后将介绍多少个有关怎么样行使
fn:collection XQuery 函数的示范。

乘势最新版本的Oracle数据库Oracle
9i的产出,又推荐了崭新的一组示例方式,它们的靶子是扩大SCOTT情势向用户提供的效率。所有这几个形式一起形成了一如既往的虚拟公司的一局地,它们分别都有友好的作业重点。例如,人力资源部、订单输入部门以及发货部门都有分别的格局。

查询 XMLType 数据

注意:

XQuery 使您可以操作基于 XML
格局以及非基于方式的数量。以下示例演示了怎么使用 XMLTable 函数从 OE
演示数据库形式中询问基于 PurchaseOrder XML 情势的 XMLType 表。

眼下hr已经锁定了(即lock)。要求实践以下脚本:

SELECT ttab.COLUMN_VALUE AS OrderTotal FROM purchaseorder,
XMLTable(
'for $i in /PurchaseOrder
where $i/User = "EABEL"
return;

{$i/Reference}

{fn:sum(for $j in $i/LineItems/LineItem/Part
return ($j/@Quantity*$j/@UnitPrice))}

'
PASSING OBJECT_VALUE
) ttab;
SQL> connect system/zyf;

已连接。

SQL> alter user hr account unlock;

用户已更改。

SQL> alter user hr identified by hr;

用户已更改。

SQL> connect hr/hr;

已连接。

SQL> select table_name from user_tables;

TABLE_NAME

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

COUNTRIES

DEPARTMENTS

EMPLOYEES

JOBS

JOB_HISTORY

LOCATIONS

REGIONS

已选择7行。

在上述示例中,您在 XMLTable 函数的 PASSING 子句中选用 OBJECT_VALUE
虚拟列将 purchaseorder 表作为左右文项传递给此间使用的 XQuery
表明式。XQuery 表明式统计用户 EABEL
请求的各类购买订单的累计,并为处理的每个订单生成一个 OrderTotal XML
元素。要访问生成的 XML,请使用 SELECT 列表中的 COLUMN_VALUE
虚拟列。最终的出口应如下所示:

4.1 SCOTT模式

所提供的SCOTT情势可以提供一些示例表以及数据,来体现数据库的一对特征。它是一个分外简单的方式,如图4-1数据结构图所示(通过PowerDesign逆向工程转换为数据库模型)。

图4-1 SCOTT方式数据结构图

 爱博体育app手机版 1

为啥要将以此格局命名为SCOTT呢?SCOTT/TIGER是Oracle版本1、2和3时代的Oracle数据库的早期用户名/密码组合。SCOTT是指Oracle集团的武夷山北斗程序员Bruce斯科特(Scott)。当然,TIGER是布鲁斯(Bruce)养的猫的名字。

SCOTT格局中所体现的数据库特性经常被认为是多数关周密据库产品中的首要特征。如若想要真实地呈现Oracle数据库的效应,就要强化这几个示例!

ORDERTOTAL
-------------------------------------------------------------

EABEL-20021009123338324PDT
1328.05


EABEL-20021009123335791PDT
2067.15


EABEL-20021009123336251PDT
289.6


EABEL-20021009123336382PDT
928.92

4.2 Oracle 9i示例方式

Oracle技术可以运用于各类不相同的条件中。技术解决方案的三个应用极端意况是,高速在线事务处理和数据库仓库。即使用户能够拔取一个格局,显示什么在相同的表中已毕在线事务处理和数据仓库。不过用户毫无可能应用那种措施已毕实用的缓解方案。我们在今日的业界中时时可以窥见,为了化解现实世界中的分歧总括需求,经常在单身的数据库实例中会存在分歧的方式,或者在网络上会有恢宏分布式数据库。新的Oracle
9i示例方式模型极好地对那几个场地建模。

Oracle
9i示例形式试图模型化一个切实世界中有所一文山会海典型业务部门的行销团队。那么些不一样的机关所有区其他音讯技术须求,每一个演示情势都选用了不一样的Oracle技术来解决它们分其他题材。别的,每个情势设计方案都对准一定的技艺用户。那些情势如下:

  • HR——人力资源。
  • OE——订单输入。
  • PM——产品媒体。产品媒体在数据库中储存了商家体系产品的连带多媒体内容,能够用来在Web上披露以及打印。PM利用了Oracle
    Intermedia,它更加陈设用来拍卖揭橥音频、视频以及可视数据的多媒体领域。此外,PM也反复地使用了LOB列类型。
  • QS——队列运送。运送部门承担记录公司向客户开展的出品运载情形,并且应用6个形式来形成那项工作。QS、QS_ES、QS_WS、QS_OS、QS_CB和QS_CS构成了队列运送情势的集合。
  • SH——销售历史。

要博取同样的最终结果,可以改用 XMLQuery 函数。但一旦将上一个演示中采纳的
XQuery 表明式参数传递给 XMLQuery(如下所示):

4.2.1 深远商讨各样情势

SELECT XMLQuery('for $i in /PurchaseOrder
where $i/User eq "EABEL"
return 
{$i/Reference}

{fn:sum(for $j in $i/LineItems/LineItem/Part
return ($j/@Quantity*$j/@UnitPrice))}

'
PASSING OBJECT_VALUE
RETURNING CONTENT)
FROM purchaseorder;

1. 人力资源

人力资源方式,或者HR形式,负责管理部门、雇员、工作以及薪资音信。图4-2突显了HR形式的事无巨细数据结构图示。

爱博体育app手机版 2

爱博体育app手机版,则 XQuery 表明式返回的空序列将与 purchaseorder
表联接,从而包含在查询统计果集中。实际上,那代表输出将不仅仅富含为用户
EABEL 请求的订单生成的 OrderTotal 元素,而且还蕴藏为 purchaseorder
表中贮存的富有其余订单生成的空行(默许境况下,purchaseorder 表包蕴 132
行)。从结果集中拔除空行的主意之一是在 SELECT 语句的 WHERE 子句中运用
existsNode SQL 函数,而不是在 XQuery 表明式中行使 WHERE 子句,如下所示:

2. 订单输入

订单输入(Order
Entry)格局,或者OE情势,可以用来管理集团从事商务活动的逐一渠道中的客户、销售订单以及产品库存。

图4-3详细刻画了OE格局的数据结构。就像大家在此此前通晓的,与人力资源方式比较,订单输入情势越发复杂。

爱博体育app手机版 3

图4-3 OE方式数据结构

OE方式会记录产品库存。大家将会储存任意指定仓库中指定产品的数码。在店铺中会有多少个仓库,所以要运用地方标识符提出其地理区域。在WAREHOUSES表中还有一个Oracle
Spatial列,它为大家提供了动用Oracle Spatial空间技术的钥匙。

Oracle Spatial是在数据库中接济地方数据和地理数据的技艺。

在OE形式中,须求顺便提供提及八个数据库对象模型:

  • CUST_ADDRESS_TYP。那是一个在CUSTOMERS表中应用的对象类型。它包罗了无数与客户地址有关的习性。

SQL> desc cust_address_typ;

名称 是否为空? 类型

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

STREET_ADDRESS VARCHAR2(40)

POSTAL_CODE VARCHAR2(10)

CITY VARCHAR2(30)

STATE_PROVINCE VARCHAR2(10)

COUNTRY_ID CHAR(2)
  • PHONE_LIST_TYP。这是一个VARCHAR2(25)的VARRAY。那个VARRAY在CUSTOMERS表中作为独立的列存储,可以用来存储最多5个电话号码。

SQL> desc phone_list_typ;

phone_list_typ VARRAY(5) OF VARCHAR2(25)

OE方式是一个很好的以身作则,它显得了业内的供应协会或者电脑零售商店可以接纳什么形式去管理它们完整订单处理进程。通过使用订单输入表中的数码,销售团队就足以向地下的客户提供标准的成品信息,接受销售订单,量化订单收入,存储客户音信,为不一样地理地点订购产品的客户提供可看重的库存信息,以及别的服务。

SELECT XMLQuery('for $i in /PurchaseOrder
return 
{$i/Reference}

{fn:sum(for $j in $i/LineItems/LineItem/Part
return ($j/@Quantity*$j/@UnitPrice))}

'
PASSING OBJECT_VALUE
RETURNING CONTENT) AS ordertotal
FROM purchaseorder
WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[User = "EABEL"]') = 1;

3. 出品媒体

出品媒体(Product
Media)方式,或者PM格局,用于管理描述集团出品的多媒体数据。录像、音频和图像那样的在线媒体都足以随输出的媒体数据类型存储在数据库中。那是我们要专门商量的方式之一,它重视于多媒体内容,以及Oracle
Intermedia所提供的功能。

注意:

Oracle Intermedia是Oracle数据库帮衬多媒体内容类型的零件。

除此之外Intermedia数据存储以外,PM形式还专程看重LOB列类型的使用来储存数据。

产品媒体格局是Oracle 9i使用名为Oracle
Intermedia的Oracle技术解决具体世界商务须求的好好示例。例如,大家虚构的营业所就足以储存多媒体数据照旧输出多媒体数据。因而,产品媒体情势中的示例可以完毕如下工作:

  • 为Oracle中选取Web发表的始末存储缩略图和完全尺寸的图像。
  • 在Oracle中存储音频剪辑。
  • 在Oracle中蕴藏视频剪辑。
  • 对图像类型举行拍卖,以便转换成与Web包容的图像类型

运用Oracle
Intermedia,一些早已很难落到实处的职责就变得相对简单。图4-4表示为产品媒体形式,以及它对订单输入表PRODUCT_INFORMATION的引用。

爱博体育app手机版 4

图4-4 PM格局数据结构

PRINT_MEDIA表拥有一个目的类型(ADHEADER_TYP),以及在表的一一记录中贮存的靶子嵌套表(TEXTDOC_TAB)。

ORDSYS.ORD__列都是一个Intermedia对象类型。那个Intermedia对象类型不仅可以储存图像、音频、视频那样的二进制数据;还足以储存各个与多媒体类型有关的元数据。

SQL> desc ordsys.ordimage;

如上查询与本有的初阶的 XMLTable 示例生成相同的输出。

4. 队列运送

咱俩的虚拟公司想要使用新闻系统,以利于在线客户拓展自助订货。当客户开端化订货的时候,系统就须求树立订单,向客户提供账单,并且要确保可以根据客户的义务,通过适当的地面发送订货。

QS_CS形式有一个名为ORDER_STATUS_TABLE的表,可以储存订单状态。那是在总体队列运送格局安装进度中绝无仅有建立表(除了通过高档队列API建立的种类表以外)。大家不会显得与表有关的数据结构图,而是要研究为队列运送情势所树立的队列系统中的新闻流程。

图4-5所示流程图示中可以看来,为了提供一个显然、直观的预购——发货——结算循环,要在机关中间什么传递音讯。

爱博体育app手机版 5

图4-5 为队列运送(QS)格局在队列系统中建立的音讯流程

任何都要从图示顶部的订单输入发轫。Oracle
Input(订单输入)过程所生成的订单会放入New Order
Queue(新订单队列)中。那一个队列要Oracle
Entry应用处理,然后会将订单放到Booked Orders
Queue(登记订单队列)中。再将Booked Orders
Queue中的订单发往适中的运载中央(East(南边)、韦斯特(West)(西部)或者Overseas(海外)),以及客户服务部门。

在那儿,运送主题就会收到要成功的订单,并且向客户发送订货,而且客户服务部门也会发觉到订单的意况。在卓殊的运送中央,Shipping
Center(运送大旨)应用就会顶住发送订货,或者将预约调整回订单状态。一旦取得了产品,就会发送退回为订单状态的制品,并且将订单放到shipped
orders(已运送订单)队列中。

当订单发送之后,就会经过shipped orders
gueue文告客户服务和客户结算部门,并且向客户发送账单。经过结算的订单会放在比尔(Bill)ed
Orders(已结算订单)队列中,它会通报客户服务机关,然后就足以成功订单处理进程。

询问 Oracle XML DB 音讯库中的 XML 数据

5. 售货历史

后日商务条件中的集团一度意识,除非人们可以运用一种有意义并且即时的主意,按照新闻变化精确的表决报告,否则世界上的享有销售新闻都是毫无价值的。决策帮助(decision
support)就是用来描述在展开表决的历程中新闻技术利用的术语。

销售历史形式是一个观念数据仓库的示范。表会依据星型形式(star
schema)设计开展集体,在那种办法下,会有一个大的SALES表位于主旨,SALES表的外围还会有一部分小的查询表,或者维数(dimension)表。SALES表平日会有大气的多少(所有的行销实时),而维数表相对于SALES表来讲会万分小。

图4-6的数据结构图展现了销售历史情势:

爱博体育app手机版 6

图4-6 销售历史情势数据结构

为访问 Oracle XML DB 音信库中蕴藏的 XML 数据,Oracle XQuery 引入了
fn:doc 和 fn:collection XQuery 函数。使用 fn:doc,您可以查询 XML
新闻库中存储的单个 XML 文档,而 fn:collection
使你可以访问同一音信库文件夹中蕴藏的七个 XML 文档。

4.2.2 渐进学习方法

安份守己分歧的受众组织格局的措施可以鼓励新的Oracle用户通过结构化的法学习技能。例如,初学者可以从人力资源开端。那可以让他深谙关系概念、查询数据、数据库操作语言、数据库定义语言、以及部分别样基本概念。

当新Oracle用户熟稔了人力资源情势之后,可以持续分析订单输入形式。在那个新情势中,他将会遇到对象类型、XML援助、Oracle
Spatial、以及其它一些相比较高档的数据库特性。

接下去,用户可以分析任何模式所提供的特定领域。多媒体专家可以深远学习产品媒体情势。设计发布-订阅型基于信息的系统的用户可以发现,队列运送方式在她们开首攻读Oracle高级队列的时候将会相当有救助。数据仓库的热衷者最好去分析和精通销售历史方式。

正如本文此前(参阅使用关周全据构建 XML部分)介绍的言传身教所示范,使用
fn:doc 万分不难直接。它拿走表示音讯库文件资源 (URI) 的字符串并再次回到该 URI
指向的文档。要询问 fn:collection XQuery
函数的意义,同一文件夹中最少应该三个音讯库文件。若是已经运行了列表 1
中的代码,则已经制造了 /public/employees 新闻库文件夹并在其中存储了
employees.xml 文件。由此,您将急需在该公文夹中至少再创建一个 XML
文件,然后才能试用 fn:collection。列表 2 中的 PL/SQL 代码基于
SCOTT/TIGER 演示数据库形式的 dept 和 emp 表存储的关周全据构建
XML,然后将转变的 XML 文档作为 acc_dept.xml 保存到 /public/employees
音信库文件夹。要运行列表 2 中的 PL/SQL 进程,请确保以 SCOTT/TIGER
的身价登录。

4.2.3 发现越来越多关于示例格局的内容

列表 2:基于关全面据构建 XML 并将其保存到 XML 音讯库

1. 数据库对象描述

在那有的中,大家将会浏览数据库,找到属于示例情势下的靶子,然后使用SQL查询间接从数据库中赢得这几个目的的概念。

注意:

以下试验部分所需的全体脚本都足以从http://www.wrox.com/的本书可下载代码中赢得。

考试:获取数据库列表

将以下脚本保存到用户本地硬盘上名为dbls.sql的公文中(C:\oracle\ora92\bin,即sql*plus工作目录)

column object_name format a30

column tablespace_name format a30

column object_type format a12

column status format a1

break on object_type skip 1

select object_type,object_name,

decode(status,'INVALID','*','') status,

tablespace_name

from user_objects a,user_segments b

where a.object_name=b.segment_name(+)

and a.object_type=b.segment_type(+)

order by object_type,object_name

/

column status format a10

运作以下代码可获得数据库对象列表:

SQL> connect hr/hr;

已连接。

SQL> @dbls
DECLARE
XMLdoc XMLType;
BEGIN
SELECT XMLQuery(
'for $j in ora:view("SCOTT", "dept")/ROW
where $j/DEPTNO = 10
return ( 
{$j/DEPTNO,
$j/DNAME}
 {
for $i in ora:view("SCOTT", "emp")/ROW
where $i/DEPTNO = $j/DEPTNO
return (

{$i/EMPNO,
$i/ENAME,
$i/SAL}
)} 

)'
RETURNING CONTENT) INTO XMLdoc FROM DUAL;
IF(DBMS_XDB.CREATERESOURCE('/public/employees/acc_dept.xml', XMLdoc)) THEN
DBMS_OUTPUT.PUT_LINE('Resource is created');
ELSE
DBMS_OUTPUT.PUT_LINE('Cannot create resource');
END IF;
COMMIT;
END;
/

2. 自解释格局

Oracle提供了一种可以让表的主人在数据库中存储表或者列的纯文本注释的不二法门。在示范情势安装时期,每个方式都抱有一个本子,可以为它们各自的表和列建立这个注释。那可以运用SQL命令CREATE
COMMENT落成。其中注释样本如下:

COMMENT ON TABLE jobs

IS ‘jobs table with job titles and salary ranges.Contains 19 rows.

References with employees and job_history table.’;

那儿,/public/employees
新闻库文件夹应涵盖多个公文:acc_dept.xml(由列表 2 中的 PL/SQL
代码生成)和 employees.xml 文件(由列表 1 中的代码生成)。由于那几个 XML
文档存储在相同音信库文件夹中,因而得以应用 fn:collection 函数访问多个XML 文档中存储的职工音信。不过,固然这么些 XML 文档均包蕴员工 XML
元素(那个要素实际上具有同样结构),但 XML 文档本身的构造迥然不一样。在
employees.xml 中,文档根元素为 EMPLOYEES,而 acc_dept.xml 将 DEPARTMENT
用作根元素。要缓解此问题,可以通过 XQuery 使用 XPath // 构造,从而导航到
XML 文档中的某个节点,而毋庸指定该节点的适合路径。以下示例演示了咋样在
XQuery 表达式中接纳 XPath // 构造:

4.3 小结

作品根据自己精晓浓缩,仅供参考。

摘自:《Oracle编程入门经典》 南开大学出版社 http://www.tup.com.cn/

SELECT XMLQuery(
'for $i in fn:collection("/public/employees")//EMPLOYEE
where $i/SAL >= 5000
order by $i/ENAME
return;
$i'
RETURNING CONTENT) FROM DUAL;

该协会应生成以下输出:

102
De Haan
17000


7839
KING
5000


100
King
24000


101
Kochhar
17000

您可以观看,以上输出包含从 employees.xml 和 acc_dept.xml 中赢得的员工
XML 元素,那个因素表示薪俸大于或等于 5,000 比索的职工。

将 XML 分解为关周到据

如若应用程序处理关周密据而非 XML,而你须要拜访的多少以 XML
格式存储,则将 XML
分解为关全面据可能会非凡管用。继续开展上有些的以身作则,您可以动用 SQL
函数 XMLTable 将职工 XML 元素分解为虚拟表的单个列,如下所示:

SELECT emps.empno,emps.ename, emps.sal FROM 
XMLTable(
'for $i in fn:collection("/public/employees")//EMPLOYEE
where $i/SAL >= 5000
return;
$i'
COLUMNS empno NUMBER PATH '/EMPLOYEE/EMPNO',
ename VARCHAR2(30) PATH '/EMPLOYEE/ENAME',
sal NUMBER PATH '/EMPLOYEE/SAL') emps;

该查询将转移以下输出:

EMPNO ENAME SAL
----- -------------- ----------
7839 KING 5000
100 King 24000
101 Kochhar 17000
102 De Haan 17000

询问外部数据源

使用 XQuery,能够依据 XML 数据以及能够用 XML 表示的非 XML 数据生成 XML
文档,无论其义务怎么:无论是存储在数据库中、置于网站上、即时创造或者存储在文件系统中。但要注意,Oracle
XML DB 为针对数据库中储存的数量开展的 XML
操作提供了老大高的性质和可伸缩性。因而,即使你可以完全控制所处理的数额,则最好将它移动到数据库中。

正如您从前边的演示中明白到的,在 Oracle XQuery 实施中,doc 和 collection
XQuery 函数用于访问 Oracle XML DB 音讯库中贮存的 XML 文档。可以经过
XMLTable 和 XMLQuery SQL 函数中的 PASSING
子句动态绑定外部数据源。考虑以下示例。假如你的营业所要为那一个从事于 XQ
项目标职工花费奖金。由此,财务部公布了 empsbonus.xml
文件,其中带有有身份取得奖金的职工列表以及该列表中输入的每个员工的奖金多少。empsbonus.xml
文件或者如下所示:

100
1200


101
1000

在其实情状中,以上的 XML
文件或者置于网站上(因而可以通过互联网得到)、以文件方式储存在本土文件系统中,或以文件资源格局储存在
Oracle XML DB
音信库中。就本示例而言,该公文位于网站上。为简便起见,可以在目录(Web
服务器在里边蕴藏可从 Web
看到的文档)中创建一个职工文件夹,然后在该文件夹中插入 empsbonus.xml
文件,以便可以因此以下 URL 访问 empsbonus.xml 文件:

http://localhost/employees/empsbonus.xml

接下去,即使您必要按照 empsbonus.xml
文档中存储的数目创立一个报表。在该报表中,您或许非但要包括列表中突显的奖金多寡以及各类员工的员工
ID,还要包罗他/她的真名。因而,可以率先拔取以下查询生成一个新的 XML
文档(如果你以 HR/HR 的地位连接):

SELECT XMLQuery(
'for $k in 1
return (
 {for $i in ora:view("employees")/ROW,
$j in $emps/EMPLOYEES/EMPLOYEE
where $i/EMPLOYEE_ID = $j/EMPNO
return (
{xs:string($i/EMPLOYEE_ID)}
{xs:string(fn:concat($i/FIRST_NAME, " ", $i/LAST_NAME))}
{xs:integer($j/BONUS)}
)} )'
PASSING xmlparse (document httpuritype
('http://localhost/employees/empsbonus.xml').getCLOB()) as "emps"
RETURNING CONTENT).getStringVal() as RESULT FROM DUAL;

上述查询是一个关于怎样运用 XQuery 基于 XML 和非 XML
数据(以分裂的艺术从不相同的多寡源中检索)生成 XML
文档的演示。具体而言,使用 ora:view() 函数访问 HR 演示方式中的默许
employees 关系表,并使用 PASSING 子句中的 httpuritype() 函数借助于
HTTP 访问 empsbonus.xml 文档。然后,在 FLWOR 表明式的 return
子句中构建新的 XML 文档。最后,将赢得以下 XML 文档:


100
Steven King
1200


101
Neena Kochhar
1000

化解性能问题

正如你此前方的片段中打探到的,XQuery 是一种用于查询 Oracle 数据库存储的
XML 内容的很快方法 – 无论你是处理地点存储的 XMLType
数据照旧查询基于关全面据构建的 XML
视图。但依照对数码利用的储存类型的两样,XQuery
说明式的推行性能可能截然不一致不一样。尤其是,Oracle XML DB 可以优化基于由
ora:view 函数创立的 SQL/XML 视图而构建的 XQuery 表明式。对于 XMLType
表或列中储存的 XML 数据,只好对使用结构化(对象-关系)存储技术存储的基于
XML 情势的 XMLType 数据开展 XQuery 优化。

所接纳的仓储模型并非是影响 XQuery
表明式执行性能的绝无仅有要素。在一些境况下,XQuery
表明式本身的社团也恐怕引致性能问题。要监控 XQuery
表明式的性质,可以打印并检讨关联的 EXPLAIN PLAN。在 SQL*Plus
中,只需安装 AUTOTRACE 系统变量,即可打印 SQL
优化程序选取的举行路径。但要执行该操作,请保管创立 PLUSTRACE
角色,然后将其授予连接到数据库所接纳的用户。有关怎样举办此操作的信息,请参阅
Oracle 数据库 10g 第 2 版 (10.2) 文档中《SQL\Plus
用户指南和参照》一书中的“调整
SQL\
Plus”一章。以下示例演示了怎样通过检查 EXPLAIN PLAN
生成的实施安插来博取利益。如若你曾经将 PLUSTRACE 角色赋予默许用户 OE,以
OE/OE 的地位登录并运行以下查询:

SET AUTOTRACE ON EXPLAIN
SELECT count(*)
FROM oe.purchaseorder, XMLTable(
'for $i in /PurchaseOrder/User
where $i = "CJOHNSON"
return $i'
PASSING OBJECT_VALUE) ptab;

那将扭转以下输出:

COUNT(*)
----------
9
Execution Plan
---------------------------------------------
Plan hash value: 4046110317
--------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 226 | 29 (0) | 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 226 | | |
| 2 | NESTED LOOPS | | 10782 | 2379K | 29 (0) | 00:00:01 |
|* 3 | TABLE ACCESS FULL | PURCHASEORDER | 1 | 226 | 5 (0) | 00:00:01 |
| 4 | COLLECTION ITERATOR P| XMLSEQUENCEFROMX| | | | |
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter(SYS_CHECKACL("ACLOID","OWNERID",xmltype('...

你或许对为上述查询生成的举行安排并不合意。尤其是,所拍卖的行数可能尤其大。由于
SQL
调整的重大目的是防止访问对结果没有其余影响的行,因而恐怕要再而三调整查询以优化性能。对查询中包括的
XPath 表明式举行再度建模后,能够重新重试它,如下所示:

SELECT count(*)
FROM oe.purchaseorder, XMLTable(
'for $i in /PurchaseOrder
where $i/User = "CJOHNSON"
return $i/User'
PASSING OBJECT_VALUE) ptab;
这次,输出应如下所示: 
COUNT(*)
----------
9
Execution Plan
---------------------------------------------------
Plan hash value: 3411896580
---------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 29 | 7 (0) | 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 29 | | |
| 2 | NESTED LOOPS | | 1 | 29 | 7 (0) | 00:00:01 |
| 3 | FAST DUAL | | 1 | | 2 (0) | 00:00:01 |
|* 4 | TABLE ACCESS FULL | PURCHASEORDER | 1 | 29 | 5 (0) | 00:00:01 |
Predicate Information (identified by operation id):
---------------------------------------------------
4 - filter("PURCHASEORDER"."SYS_NC00022$"='CJOHNSON' AND
SYS_CHECKACL("ACLOID","OWNERID",xmltype('...

您可以见见,以上显示的查询生成相同的末梢结出,但它们的进行安顿并差异。查看最终一个示范中的
XQuery 表达式,您或许会小心到它迭代顶层 PurchaseOrder 元素,其中的每个
PurchaseOrder 元素都意味依照 PurchaseOrder XMLType
形式的表中的一行。那意味实际上重写 XQuery
表明式,以迭带基础对象表(用于存储分解的 PurchaseOrder
文档)中的行。与查询要迭代不意味着基础表中的单个行的 XML
元素相比,该方法的性能更好有的。

但在少数情形下,很难发现 XQuery
表明式的哪些构造将使少数查询的性质更好。那就是干什么最好在开发阶段使用调整工具的原故。

将动态变量绑定到 XQuery 表明式

另一种可以一目精晓拉长 XQuery
表明式执行性能的技艺是应用绑定动态变量。使用绑定变量(而不是将变量串联为字符串)可以使
Oracle 重用 SQL 语句,从而减弱分析开销并肯定进步应用程序的属性。可以在
XMLQuery 和 XMLTable SQL 函数中拔取 PASSING 子句将动态变量绑定到 XQuery
表明式。该技术使您可以根据客户端代码中总计的参数动态生成 XML。列表 3
中的示例演示了怎么在从 PHP 脚本执行的 XQuery 查询中采纳绑定变量。

列表 3:使用绑定变量

//File:BindVars.php
$user = 'hr';
$pswd = 'hr';
$db ='(DESCRIPTION=
(ADDRESS_LIST=
(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))
)
(CONNECT_DATA=(SID=orclR2)(SERVER=DEDICATED))
)';
$empno=100;
$conn = oci_connect($user, $pswd, $db);
$sql = 'SELECT XMLQuery('."'".'for $i in ora:view("employees")/ROW
where $i/EMPLOYEE_ID = $empno
return (
{$i/EMPLOYEE_ID,
$i/EMAIL,
$i/JOB_ID}
)'."'".'PASSING XMLElement("empno", :empno) AS "empno"
RETURNING CONTENT).GetStringVal() AS RESULT FROM DUAL';
$query = oci_parse($conn, $sql);
oci_bind_by_name($query, ":empno", $empno, 3);
oci_execute($query);
oci_fetch($query);
$str = oci_result($query, 'RESULT');
print $str;
?>

列表 3 中显得的脚本应生成以下输出(注意,浏览器中可能不会来得标记):

100
SKING
AD_PRES

XQuery 与 XSLT

尽管 Oracle 在 Oracle XML DB 中提供了一个自带 XSLT
处理器,但在很多动静下(更加是在处理大型文档时),XQuery 对于构建 XML
更便捷。别的,XQuery 表达式平日比为同一作业设计的 XSLT
样式表更具可读性,并且更清楚。与 XSLT 一样,XQuery 不但可用来将一个 XML
文档转换为另一个 XML 文档,而且还可用以将 XML
转换为另一种基于文本的格式,如 HTML 或 WML。

在本文前边的查询 XMLType 数据部分中,您看来了一个有关使用 XQuery 将一个
XML 文档转换为另一个 XML 文档的示范。具体而言,该示例使用 XQuery
表明式计算示例数据库格局 OE 的 purchaseorder
表中贮存的订单的订单一共,然后为拍卖的种种订单生成了一个 OrderTotal XML
元素。实际上,您可以选拔 XSLT
执行同样操作。为此,您首先必要创建一个使用于 PurchaseOrder XML 文档的
XSLT 样式表,以变更对应的 OrderTotal 元素。对于此示例,能够利用列表 4
中所示的 XSLT 样式表。

列表 4:使用 XSLT 统计小计总和 (Quantity * UnitPrice)

http://www.w3.org/1999/XSL/Transform" version="1.0">



























为便利起见,您或许需求将此 XSL
样式表保存在数据库中,然后再起来运用它。例如,您可以将样式表作为文件资源保存在
Oracle XML DB
新闻库中。执行该操作的法子之一是将样式表作为文件保留到地方文件系统中,然后利用以下某个互联网协议将它移动到
XML 音信库:FTP、HTTP 或 WebDAV。假诺你曾经将列表 4 中的 XSLT 样式表作为
orderTotal.xsl 保存在 /public
音讯库文件夹中,现在可以按以下示例所示将它用作 XMLTransform SQL
函数的参数(要是你以 OE/OE 的身价登录):

SELECT XMLTRANSFORM(OBJECT_VALUE,
xdbUriType('/public/orderTotal.xsl').getXML()).GetStringVal() AS RESULT FROM
purchaseorder WHERE existsNode(OBJECT_VALUE, 
'/PurchaseOrder[User = "EABEL"]') = 1;

如上查询将拍卖用户 EABEL 请求的兼具订单(即存储在 XMLType 的默许PurchaseOrder 表中的订单)并将转变与查询 XMLType 数据部分中的 XQuery
查询同一的出口。

将列表 4 中的 orderTotal XSLT 样式表与查询 XMLType
数据部分中的示例使用的 XQuery 表达式进行相比较,您或许会小心到,XQuery
方法要比 XSLT 方法更具吸引力。至少在运用 XQuery
时,您只需编写很少的代码即可得到同等的末段结出。

询问 RSS 音信提供

是因为 RSS 信息提供精神上是一个托管的 XML 文件(RSS
音信阅读器从中得到头条消息或其余情节),因而得以像处理其余其余可以透过
Web 得到的 XML
文档那样来处理它。正如您在本文前边的查询外部数据源部分中所见,可以行使
XQuery 查询任何可以经过 URL 访问的 XML。您通过 XMLTable 和 XMLQuery SQL
函数中的 PASSING 子句动态绑定所有外部 XML 数据源。以下是一个询问 RSS
新闻提供的 XQuery 示例:

SELECT XMLQuery(
'for $i in $h//channel
return;

{$i/lastBuildDate}

{for $j in $h//item
where ora:contains($j, "PHP")
return  {($j/title, $j/link)}}

'
PASSING xmlparse (document httpuritype
('http://www.oracle.com/technology/syndication/rss_otn_news.xml').getCLOB()) as "h"
RETURNING CONTENT).getStringVal() as RESULT FROM DUAL;

该 XQuery 应生成一个 XML 文档,其中蕴藏 Oracle 技术网 (OTN) 如今宣布的与
PHP 技术相关的头条音信列表。所生成的 XML 文档可能如下所示:

Tue, 01 Nov 2005 19:37:42 GMT


http://www.oracle.com/technology/xe


http://www.oracle.com/technology/pub/articles/oracle_php_cookbook


http://www.oracle.com/technology/tech/php/zendcore/index.html

但在付出实际应用程序时,您将很可能必要 XQuery 表明式直接生成 HTML
标记,而不是一味转移一个如上所示的 XML
文档。那样,您便得以构建一个更灵敏、可维护性更高的应用程序,原因是在那种情状下,所有
RSS 处理(从提取需要的多少到将它包裹在 HTML
标记中)都将更换来数据库。那使你不用编写负责 RSS
处理的应用程序代码。实际上那表示你不用在比如 RSS
音讯提供的协会已经改成的意况下修改应用程序代码。相反,您只需修改用于 RSS
处理的 XQuery 表明式。

总结

你曾经在本文了然到,XQuery
是一个归纳的查询语言,它提供了一种用于查询、构建和转换 XML
数据的快速方法。固然 Oracle XQuery 实施使你可以操作任何可以用 XML
表示的数目(无论它存储在数据库中、位于网站上或者存储在文件系统中),但将处理的数额移动到数据库中始终是一个不易的呼声。对于数据库中储存的多少,Oracle
XML DB(对 XPath
重写使用同样机制)只好眼看优化处理那个基于以下数据构建的 XQuery
表明式:那几个数量包蕴关周详据、对象-关周到据或行使结构化(对象-关系)存储技术存储的依照XML 情势的 XMLType 数据。

(义务编辑:铭铭)

原文:Oracle
XQuery查询、构建和转换XML

重回数据库首页

相关文章