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

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情势数据结构图

 lovebet下载 1

干什么要将这多少个格局命名为SCOTT呢?SCOTT/TIGER是Oracle版本1、2和3时代的Oracle数据库的中期用户名/密码组合。SCOTT是指Oracle公司的泰斗程序员布鲁斯斯科特。当然,TIGER是布鲁斯养的猫的名字。

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情势的详实数据结构图示。

lovebet下载 2

则 XQuery 表明式再次回到的空体系将与 purchaseorder
表联接,从而包含在查询总结果集中。实际上,这象征输出将不仅仅含有为用户
EABEL 请求的订单生成的 OrderTotal 元素,而且还富含为 purchaseorder
表中蕴藏的具有其他订单生成的空行(默认情形下,purchaseorder 表包含 132
行)。从结果集中拔除空行的措施之一是在 SELECT 语句的 WHERE 子句中动用
existsNode SQL 函数,而不是在 XQuery 表明式中采纳 WHERE 子句,如下所示:

lovebet下载,2. 订单输入

订单输入(Order
Entry)格局,或者OE形式,可以用来保管公司从事商务活动的一一渠道中的客户、销售订单以及产品库存。

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

lovebet下载 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的引用。

lovebet下载 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所示流程图示中可以看到,为了提供一个清晰、直观的订座——发货——结算循环,要在单位之间怎样传递信息。

lovebet下载 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的数据结构图呈现了销售历史情势:

lovebet下载 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

回去数据库首页