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

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形式数据结构图

 图片 1

怎么要将以此格局命名为SCOTT呢?SCOTT/TIGER是Oracle版本1、2和3时代的Oracle数据库的早期用户名/密码组合。SCOTT是指Oracle公司的龙虎山北斗程序员布鲁斯(Bruce)斯科特。当然,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形式的详实数据结构图示。

图片 2

则 XQuery 表达式重返的空体系将与 purchaseorder
表联接,从而包含在查询总结果集中。实际上,这意味着输出将不仅仅涵盖为用户
EABEL 请求的订单生成的 OrderTotal 元素,而且还带有为 purchaseorder
表中蕴藏的兼具其他订单生成的空行(默认境况下,purchaseorder 表包含 132
行)。从结果集中拔除空行的主意之一是在 SELECT 语句的 WHERE 子句中利用
existsNode SQL 函数,而不是在 XQuery 表明式中采纳 WHERE 子句,如下所示:

2. 订单输入

订单输入(Order
Entry)形式,或者OE情势,可以用来治本企业从事商务活动的次第渠道中的客户、销售订单以及产品库存。

图4-3详尽刻画了OE格局的数据结构。就如我辈以前了然的,与人力资源模式比较,订单输入格局更加复杂。

图片 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的引用。

图片 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所示流程图示中得以看看,为了提供一个清楚、直观的预购——发货——结算循环,要在部门之间怎么样传递音讯。

图片 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文告客户服务和客户结算部门,并且向客户发送账单。经过结算的订单会放在比尔ed
Orders(已结算订单)队列中,它会打招呼客户服务机关,然后就可以完成订单处理过程。

查询 Oracle XML DB 信息库中的 XML 数据

5. 销售历史

当今商务环境中的公司一度意识,除非人们可以利用一种有含义并且即时的法门,遵照音信变更精确的决策报告,否则世界上的兼具销售音信都是毫无价值的。决策辅助(decision
support)就是用来讲述在展开裁定的长河中音信技术利用的术语。

销售历史格局是一个传统数据仓库的示范。表会依据星型形式(star
schema)设计开展集体,在这种办法下,会有一个大的SALES表位于主旨,SALES表的外围还会有一对小的查询表,或者维数(dimension)表。SALES表常常会有大量的多寡(所有的行销实时),而维数表相对于SALES表来讲会非常小。

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

图片 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

归来数据库首页

相关文章