IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Information Management | WebSphere  >

利用 WebSphere Federation Server 9.1 集成 XML 数据

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 中级

Aakash Bordia (bordia@us.ibm.com), 资深软件工程师, IBM
Eileen Lin (etlin@us.ibm.com), 高级技术人员, IBM 
Ioana Ursu (ursu@us.ibm.com), 高级软件工程师, IBM Silicon Valley Lab
Sebastian Hahnel, 实习软件工程师, IBM

2007 年 7 月 23 日

WebSphere® Federation Server 9.1 中全新的 pureXML™ 支持让您可以集成本地和远程的 XML 存储数据。而且,您还可以使用新的 SQL/XML 和 XQuery 语言来查询新应用程序中的 XML 数据。通过本篇文章,学习如何让这个杰出组合为您所用!

简介

IBM WebSphere Federation Server 可提供对数据源的实时虚拟访问。这样一来,您就可以以更短的上市时间发布新的 projesources. cts、用特殊查询扩展数据仓库并为企业数据生成统一的视图。

由于 DB2® 9 提供了对 pureXML 的支持,因此 WebSphere Federation Server 9.1 就让您能够集成单一数据库中的关系数据和 XML 数据。联邦技术的用户现在可以将原生 XML 存储内的新 XML 数据集成到联邦数据库内。虽然现在尚不能直接支持远程 XML 数据类型,但联邦用户通过 XML 视图也可以实现远程 XML 数据的集成。

本篇文章展示了如何借助 WebSphere Federation Server 9.1 集成本地和远程的 XML 存储数据。以书店场景为例,让我们看看如何使用新近增强的 SQL/XML 和新 XQuery 语言来处理本地 XML 存储数据。然后,再来探讨一下集成远程 XML 存储数据所需的配置步骤及相关考虑。之后,将书店场景扩展到分布式书店场景,展示如何将配置应用到各种数据源。我们还提供了一些查询示例,以让您能亲历如何使用 SQL/XML 和 XQuery 语言查询这样的系统的全过程。结束语一节概况了我们现在正努力要实现的各种增强以使这种特性更易于将来使用。

集成本地 XML 存储数据

DB2 支持 SQL 和 XQuery 作为其主要的查询语言。二者均能在各自不同的数据模型上工作,且均可以独立使用。若 DB2 支持的这两种语言能够集成,那么数据库应用程序 将会从中受益颇多。由于很多应用程序都会同时处理现有的关系数据和 XML,因此查询需要结合和关联这两种类型的数据。为支持这类集成 ,DB2 9 提供了如下函数:

  • SQL/XML 函数和谓词,可让应用程序访问 SQL 内的 XML 数据。
  • 诸如 db2-fn:sqlquery 这类函数,可让应用程序访问 XQuery 中的关系数据。

由于 DB2 通过联邦能提供到异构关系数据的透明访问,因此在 SQL/XML 和 XQuery 内指定的关系表就有可能是昵称。

在本节,我们将来探讨一下如何使用 SQL/XML 和 XQuery 查询本地 XML 列和昵称。 讨论过程中会用到图 1 所示的场景。


图 1. 书店场景

图 2 展示了此场景的配置:


图 2. 书店场景的配置

用 SQL 查询本地 XML 数据和昵称

DB2 通过提供诸如 XMLQUERYXMLEXISTSXMLTABLE 这样的新的 SQL/XML 函数和谓词实现对 SQL 语句中的 XML 数据的检索和查询。让我们先来看看这个简单的示例。如下的查询检索书的相关信息、书的剩余库存数量以及存有 ISBN 号以 “69” 结尾的那些书的仓库所在城市:

SELECT b.xmlinfo, i.quantity, w.city  
FROM bookstore b, inventory i, warehouse w  
WHERE b.isbn = i.isbn 
  AND i.warehouse_id = w.warehouse_id 
AND b.isbn LIKE '%69'

在上例中,我们连接了两个昵称和一个包含 XML 列的本地表。

示例输出(显示为 prettyPrint)应该如下所示:

<book isbn="0201633469" year="1993" category="Computers">
  <title>TCP/IP Illustrated</title>
  <author><last>Stevens</last><first>W. Richard</first></author>
  <publisher>Addison-Wesley Professional</publisher>
  <price>65.00</price>
</book>,
3,
'San Francisco'

下一个示例使用 XMLTABLE 函数从本地 XML 列返回结果表,然后使用结果表来将数据插入到昵称内。目的是通过从书店表的 XML 文档提取数据以将书的作者信息存储到单独的一个表内。

INSERT INTO author
  SELECT xb.*
  FROM bookstore b, XMLTABLE(
    '$doc/book' PASSING b.xmlinfo AS "doc" COLUMNS
      "ISBN" CHAR(10) PATH '@isbn',
      "LASTNAME" VARCHAR(30) PATH 'author/last',
      "FIRSTNAME" VARCHAR(30) PATH 'author/first'
    ) AS xb;

下一个示例返回全部书店文档,并用 XMLEXISTS 进行额外的过滤。只有那些单价低于 $65.50 且仓库尚有存货的那些书的记录才会被返回。 passing by 子句建立了 SQL 和 XQuery 上下文间的绑定。

SELECT b.isbn, i.warehouse_id, i.quantity
FROM bookstore b, inventory i
WHERE i.isbn = b.isbn 
  AND i.quantity > 0
  AND XMLEXISTS('$doc/book[price < 65.50]' 
        PASSING BY REF b.xmlinfo AS "doc")

下一个示例显示了 WHERE 子句的 XMLQUERY 函数,以便从本地 XML 列提取出的数据能用来与昵称列连接。这里,对于每个标题中包含关键字 “TCP/IP” 的每一本书,我们都会查找该书作者出版的所有书的总数:

SELECT DISTINCT count(*) as NUMBER_OF_BOOKS, a.firstname, a.lastname
FROM author a, bookstore b
WHERE XMLSERIALIZE(CONTENT XMLQUERY('$doc/book/author/first/text()'
    PASSING BY REF b.xmlinfo AS "doc"
    RETURNING SEQUENCE) AS CHAR(50)) = a.firstname
  AND XMLSERIALIZE(CONTENT XMLQUERY('$doc/book/author/last/text()'
    PASSING BY REF b.xmlinfo AS "doc"
    RETURNING SEQUENCE) AS CHAR(50)) = a.lastname
  AND XMLSERIALIZE(CONTENT XMLQUERY('$doc/book/title/text()'
    PASSING BY REF b.xmlinfo AS "doc"
    RETURNING SEQUENCE) AS CHAR(50)) like '%TCP/IP%'
GROUP BY a.firstname, a.lastname, b.isbn

用 XQuery 查询本地 XML 数据和昵称

可以在 DB 9 中使用 XQuery 来访问和检索关系数据。这是通过 SQL/XML 构造函数实现的,这些函数能够把关系数据转换成 XML 格式并能生成类型 XML 的单个行,将其作为到 XQuery 的输入。用户可以使用所有现有的关系数据以使 XML 能够适合 XQuery 处理。 db2-fn:sqlquery 函数不仅可以用来减少到 XQuery 的输入,而且还能扩展它。

在以下的示例中,XQuery 构造结果文档,该文档包含书、库存和书的特定信息。书的信息是一个从 XML 列 XMLINFO 检索出来的 XML 文档。库存信息则来自两个关系昵称的连接。SQL/XML 语句构造一个具有五个子元素的 XML 元素 warehouse,这些子元素(比如仓库 ID、街道、城市、州和数量)的值取自两个昵称 WAREHOUSEINVENTORY 连接的结果。结果文档是某本书的一个库存报告,并注有关于仓库的信息。

XQUERY 
  let $b := db2-fn:sqlquery("
    SELECT xmlinfo
    FROM bookstore
    WHERE isbn='0201633469'")
  let $w := db2-fn:sqlquery("
    SELECT XMLELEMENT(NAME warehouse, XMLFOREST(
      w.warehouse_id, w.street, w.city, w.state, i.quantity))
    FROM warehouse w, inventory i
    WHERE w.warehouse_id = i.warehouse_id
    AND i.isbn = '0201633469'")  
  return 
    <report>   
     {$b}
     <stock>{$w}</stock>
    </report>

示例输出(显示为 prettyPrint)应该如下所示:

<report>
  <book isbn="0201633469" year="1993" category="Computers">
    <title>TCP/IP Illustrated</title>
    <author><last>Stevens</last><first>W. Richard</first></author>
    <publisher>Addison-Wesley Professional</publisher>
    <price>65.00</price>
  </book>
  <stock>
    <WAREHOUSE>
      <WAREHOUSE_ID>1</WAREHOUSE_ID>
      <STREET>1234 Market Street</STREET>
      <CITY>San Francisco</CITY>
      <STATE>CA</STATE>
      <QUANTITY>3</QUANTITY>
    </WAREHOUSE>
    <WAREHOUSE>
      <WAREHOUSE_ID>2</WAREHOUSE_ID>
      <STREET>4012 1st Street</STREET>
      <CITY>San Jose</CITY>
      <STATE>CA</STATE>
      <QUANTITY>1</QUANTITY>
    </WAREHOUSE>
  </stock>
</report>

下一个示例通过与昵称连接过滤一组到 XQuery 的输入文档。 我们查询 ID 等于 1 的仓库中列出的单价高于 $65 的书的标题。

XQUERY 
  for $e in db2-fn:sqlquery("
    SELECT b.xmlinfo 
    FROM bookstore b, inventory i
    WHERE b.isbn = i.isbn 
     AND i.warehouse_id = 1")/book
  where $e/price > 65.00
  return $e/title

示例输出(显示为 prettyPrint)应如下所示:

<title>Advanced Programming in the UNIX environment</title>

以上这些示例突出展示了 XQuery 和 SQL 集成后的强大功能,尤其是,经由昵称访问的关系数据可与原生 XML 存储一同使用。

集成远程 XML 存储数据

在 WebSphere Federation Server 9.1 内,昵称不能在包含 XML 类型列的远程表或视图之上创建。要从各种关系数据库集成 XML 数据,可以将在序列化的 XML 字符串数据之上使用视图作为一种机制来映射远程和本地 XML 数据。

图 3 展示了如下步骤:

  1. 通过视图在远程数据库之上序列化 XML 数据
  2. 在此远程视图之上创建昵称
  3. 将序列化后的 XML 数据从本地昵称解析进联邦服务器上的本地视图

图 3. 如何集成远程 XML 数据的图形视图

假设有一个远程 Oracle 表,该表具有如下定义:

CREATE TABLE bookstore(isbn CHAR(10), xmlinfo XMLType);

接下来,XML 数据在远程服务器被序列化成如下视图:

CREATE VIEW bookstore_blob (isbn, xmlinfo) AS
SELECT b.isbn, b.xmlinfo.getBlobVal(nls_charset_id('utf8'))
FROM bookstore b;

XML 数据没有固定长度。因为要包括大型文件,外部的 XML 数据类型将被以与 LOB 数据相同的方式处理。然而,对于较小的文件,也可以指定像 VARCHAR 这样的结果类型,与 Character Large Objects (CLOB) 比较而言,这种类型可能更为合适而且也会产生更好的性能。

远程 XML 数据被序列化后,您就能够在联邦服务器在远程视图之上创建昵称,如下所示:

CREATE NICKNAME bookstore_blob FOR server_name.myuser.bookstore_blob;

接下来,在联邦服务器,需要将序列化后的字符串转换回 XML 类型。让我们使用 XMLPARSE 函数,该函数将序列化后的字符串转换成 XML 值,如下面的语句所示:

CREATE VIEW vbookstore (isbn, xmlinfo) AS
SELECT isbn, XMLPARSE(DOCUMENT xmlinfo PRESERVE WHITESPACE)
FROM bookstore_blob;

现在,就可以借助 XQuery 和 SQL/XMLNow 函数像处理本地 XML 数据类型一样地处理远程 XML 数据。

远程 XML 数据的数据验证

DB2 解析器只允许将有效的 XML 数据作为输入。如果所提供的数据不能被解析,就会返回错误。比如,您也可以在远程视图之上创建昵称,这个远程视图提取部分 XML 文档或元素的值。如下的 Oracle 视图将会返回 XML 元素的内容:

CREATE VIEW bookstore_blob (isbn, xmlinfo) AS
SELECT extract(xmlinfo, '//book').getBlobVal(nls_charset_id('utf8'))
FROM bookstore;

其结果是作为 XML 类型的实例返回的节点序列。如果 XMLPARSE 被应用于在上述远程视图之上创建的昵称的输出,那么 DB2 解析器就可能会报告这个包含无效 XML 文档结构 (SQL16132N) 的 XML 文档。这可以被认为是一个使用错误。

解决此错误的一种方式是添加作为视图定义一部分的 root 元素。例如,可以在 Oracle 数据源上创建如下视图:

CREATE VIEW bookstore_blob (isbn, xmlinfo) AS
SELECT '<root>' || 
       extract(xmlinfo,//book').getBlobVal(nls_charset_id('utf8'))|| 
       '</root>' 
FROM bookstore;

而且,在联邦服务器上,您可以使用模式验证和 XMLPARSE

CREATE VIEW vbookstore (isbn, xmlinfo) AS
SELECT isbn, XMLVALIDATE(XMLPARSE(DOCUMENT xmlinfo WHITESPACE)
                          ACCORDING TO XMLSCHEMA ID bookschema)
FROM bookstore_blob;

bookschema 是本地 DB2 注册的模式对象,该目标可以代表本地数据源 XML 模式。可以使用 REGISTER XMLSCHEMA 命令注册书店模式,如以下的示例所示:

REGISTER XMLSCHEMA schema_URI FROM content_URI AS bookschema COMPLETE;

默认情况下,XMLPARSE 只检查格式良好的数据(无模式验证)。

XMLVALIDATE 函数针对给定的或从实例文档的模式规范中获得的 XML 模式验证给定的 XML 值。

请注意以下的一些限制:

  • 如果 XMLVALIDATE 在没有任何模式规范的情况下被调用,那么就使用内部模式规范或者是 DTD 规范(如果没有内部规范)。如果访问不了模式位置或外部 DTD,解析器就会发出错误消息。
  • 如果通过注册的模式或指定的 URI 调用了 XMLVALIDATE,那么验证就会针对特定模式执行。如果指定了一个外部模式,那么此外部模式会改写内部模式规范。对于联邦语句而言,如果模式信息不能由 DB2 服务器访问,那么就会改写文档的内部模式规范。

远程 XML 数据的数据编码考虑

当序列化 XML 数据时,目标类型决定了所使用的编码类型。XML 输出将包含内部编码信息。然而,非 XML 输出可能并不会包括 XML 声明,在这种情况下,将由联邦服务器或 DB2 XML 解析器来决定编码方案。

总的来说,如果 XML 数据是通过 XML 数据类型发送和接受的,就不需要考虑代码页转换问题。但,当 SQL 字符类型被用来保存序列化的 XML 数据时,字符类型的代码页就可能会带来代码页转换问题。

对于联邦语句而言,在处理序列化后的远程 XML 数据时,有可能会发生如下与代码页相关的问题:

远程 XML 数据被序列化成二进制数据类型。

从远程客户机传到联邦包装器时数据没有丢失。

需要应用 DB2 XML 解析器编码规则。另外,如果内部编码虽然存在但却不是一个有效的 IBM 编码模式,解析器将会发出 SQL16168N 错误消息。在这种情况下,建议从远程序列化的字符串中排除 XML 声明。例如,在 Oracle,可以使用如下的远程视图定义来排除 XML 声明。如果 XML 声明存在于 XML 文档内,Oracle 会默认添加此 XML 声明。

CREATE VIEW bookstore_blob (isbn, xmlinfo) AS
SELECT isbn, 
extract(xmlinfo,'/').getBlobVal(nls_charset_id('utf8'))
FROM bookstore;
		  

远程 XML 数据被系列化成字符数据类型:

  • XML 数据的代码页即是联邦数据库的代码页 (Unicode)。从远程客户机传到联邦包装器时数据有可能会丢失。如果转换导致了字符替代,就会根据数据源行为和包装器实现生成一条警告消息。
  • 需要应用 DB2 XML 解析器编码规则。如果内部编码存在且为一个无效的 IBM 编码模式,解析器将会发出 SQL16168N。在这种情况下,如果序列化允许,建议排除 XML 声明。例如,可以使用如下的远程视图定义来排除 XML 声明:
CREATE VIEW clob_books (isbn, xmlinfo) AS
SELECT isbn, extract(xmlinfo, '/').getClobVal() 
FROM bookstore;

要避免代码页转换的问题,建议使用字符 FOR BIT DATABLOB 代替字符类型。对于联邦系统,注意内部编码跨各种数据源可能会不同。在这种情况下,如果序列化允许,建议排出 XML 声明。

分布式书店场景

结合在 集成本地 XML 存储数据 一节介绍的场景,来看看 图 4 所示的实体关系图,该图描述了一个在线书店的场景。注意联邦服务器和 Oracle 10g Release 2 数据库中都有 BOOKSTORE 表。


图 4. 分布式书店场景

要获得有关如何创建服务器、包装器和用户映射的更多信息,请参考 附录 A3。完整的设置如图 5 所示:


图 5. 书店场景的配置

用远程视图序列化远程 XML 数据

BOOKSTORE 位于 Oracle 10gR2 服务器上。XML 数据通过如下所示的远程视图序列化到 BLOB 的数据类型:

CREATE VIEW bookstore_blob (isbn, xmlinfo) AS
SELECT b.isbn, b.xmlinfo.getBlobVal(nls_charset_id('utf8'))
FROM bookstore2 b;

REVIEW 位于 SQL Server 2005 上,其 XML 数据通过如下所示的远程视图序列化进 BLOB

CREATE VIEW review_blob (review_id, xmlinfo) AS
SELECT review_id, CAST(xmlinfo AS VARBINARY(MAX))
FROM review;

CUSTOMER_INFO 存储于 DB2 9 数据库中,其 XML 数据通过如下所示的远程视图序列化进 BLOB 列:

CREATE VIEW customer_info_blob (customer_id, xmlinfo) AS
SELECT customer_id, XMLSERIALIZE(xmlinfo AS BLOB INCLUDING XMLDECLARATION)
FROM customer_info;

创建昵称和本地 XML 视图

本例使用以下语句定义关系昵称:

CREATE NICKNAME bookstore_blob FOR "oracle10g2".myuser.bookstore_blob;
CREATE NICKNAME review_blob FOR "mssql".myuser.review_vlob;
CREATE NICKNAME customer_info_blob 
  FOR "db2v91".myuser.customer_info_blob; 
CREATE NICKNAME inventory FOR "db2v91".myuser.inventory;
CREATE NICKNAME warehouse FOR "db2v91".myuser.warehouse;

由于 orders.xml XML 文档中的客户订单包含多个项,因此要使用两个昵称加以表示:

CREATE NICKNAME order (
  order_id CHAR(10) OPTIONS (XPATH '@id'),
  order_date DATE OPTIONS (XPATH '@date'),
  customer_id CHAR(10) OPTIONS (XPATH '@cid'))  
FOR SERVER "xml_server"
OPTIONS (
  FILE_PATH '/my/path/orders.xml', 
  XPATH '/orders/order');

CREATE NICKNAME order_item (
  order_id VARCHAR(10) OPTIONS (XPATH '../@id'),
  isbn CHAR(10) OPTIONS (XPATH '@isbn'))
FOR SERVER "xml_server"
OPTIONS (
  FILE_PATH '/my/path/orders.xml', 
  XPATH '/orders/order/item');

接下来,在关系昵称之上创建本地 XML 视图:

CREATE VIEW vbookstore2 (isbn, xmlinfo) AS
SELECT isbn, XMLPARSE(DOCUMENT xmlinfo PRESERVE WHITESPACE)
FROM bookstore_blob;

CREATE VIEW vreview (review_id, xmlinfo) AS
SELECT review_id, XMLPARSE(DOCUMENT xmlinfo PRESERVE WHITESPACE)
FROM review_blob;

CREATE VIEW vcustomer_info (customer_id, xmlinfo) AS
SELECT customer_id, XMLPARSE(DOCUMENT xmlinfo PRESERVE WHITESPACE)
FROM customer_info_blob;

要对一个分布式书店建模,可在表 bookstore1 和视图 vbookstore2 之上定义 UNION ALL 视图:

CREATE VIEW big_bookstore (isbn, xmlinfo) AS
  SELECT isbn, xmlinfo FROM bookstore1
  UNION ALL
    SELECT isbn, xmlinfo FROM vbookstore2; 

用 SQL/XML 和 XQuery 进行查询

用户可以针对以上创建的本地视图发出受支持的 SQL/XML 或 XQuery,而无需知道 XML 数据位于何处。

首先,使用 SQL/XML publish 函数和 XMLTABLE 函数查找每本书的评论。

SELECT XMLELEMENT(NAME "book",
         XMLFOREST(
           b."title" AS "title", 
           r."review" AS "review"))
FROM big_bookstore vb, vreview vr,
  XMLTABLE('$doc/book' PASSING vb.xmlinfo AS "doc"
    COLUMNS "isbn" CHAR(10) PATH '@isbn',
            "title" VARCHAR(50) PATH 'title') as b,
  XMLTABLE('$doc/reviews/review' PASSING vr.xmlinfo AS "doc"
    COLUMNS "isbn" CHAR(10) PATH '@isbn',
            "review" VARCHAR(70) PATH '.') as r
WHERE b."isbn" = r."isbn";

示例输出(作为 prettyPrint)为:

<book>
  <title>Advanced Programming in the UNIX environment</title>
  <review>A clear and detailed discussion of UNIX programming.</review>
</book>
<book>
  <title>TCP/IP Illustrated</title>
  <review>One of the best books on TCP/IP.</review>
</book>

接下来,可以使用 SQL/XML 的 publish 函数和其他的 XML 构造来提供在各个地方销售的图书的列表。格式化后的输出如下所示:

<list>
  <state name="CA">
    <city name="San Francisco">
      <book>TCP/IP Illustrated</book>
    </city>
    <city name="San Jose">
      <book>Advanced Programming in the UNIX environment</book>
      <book>TCP/IP Illustrated</book>
      <book>TCP/IP Illustrated</book>
    </city>
  </state>
  <state name="NY">
    <city name="New York">
      <book>TCP/IP Illustrated</book>
    </city>
  </state>
</list>

如下语句生成了上述输出(作为一个序列):

VALUES (XMLELEMENT(NAME "list", (
  SELECT XMLAGG (s.state)
  FROM ( SELECT XMLELEMENT(NAME "state", 
           XMLATTRIBUTES(c.state AS "name"),
           XMLAGG(c.city)) AS state
         FROM ( SELECT ci."state" AS state, 
                  XMLELEMENT(NAME "city", 
                  XMLATTRIBUTES(ci."city" AS "name"),
                  XMLAGG(XMLELEMENT(NAME "book", b."title"))) AS city
                FROM order o, order_item oi, 
                     big_bookstore vb, vcustomer_info vci,
	          XMLTABLE('$p/customer' PASSING vci.xmlinfo AS "p"
		    COLUMNS "id" VARCHAR(10) PATH '@id',
			    "city" VARCHAR(20) PATH 'address/city',
			    "state" VARCHAR(10) PATH 'address/state') AS ci,
	          XMLTABLE('$p/book' PASSING vb.xmlinfo AS "p"
	            COLUMNS "isbn" VARCHAR(10) PATH '@isbn',
	                    "year" VARCHAR(4) PATH '@year',
	                    "title" VARCHAR(100) PATH 'title') AS b
                     WHERE o.order_id = oi.order_id 
                       AND oi.isbn = b."isbn"
                       AND o.customer_id = ci."id"
                       AND o.order_date <= '10/25/2004'
                     GROUP BY ci."city", ci."state") AS c 
         GROUP BY c.state) AS s
  )));

用户还可以部署 XQuery 来检索那些评价最好且单价低于平均价格的计算机图书:

 
XQUERY 
  let $a := fn:avg(
    db2-fn:xmlcolumn("BIG_BOOKSTORE.XMLINFO")
    /book[@category = "Computers"]/price/text())
  for $book in db2-fn:xmlcolumn('BIG_BOOKSTORE.XMLINFO')/book
  for $review in db2-fn:xmlcolumn('VREVIEW.XMLINFO')/reviews/review 
where 
  $book/@isbn = $review/@isbn
  and $book/price/text() <= $a 
  and fn:contains($review/text(), "best")
return 
  <book>{$book/title/text()}</book>

示例输出为:

<book>TCP/IP Illustrated</book>

这最后一个示例展示了如何在 XQuery 内使用 SQL 以及如何嵌套 XQuery 结构。本查询的目的是获得每本书在每个仓库的库存以及每本书的总库存:

XQUERY
  for $total_order in db2-fn:sqlquery('
    SELECT 
      XMLELEMENT(NAME "total_order",
        XMLFOREST(
          i.isbn AS "isbn",
          sum(i.quantity) AS "total"
        )
      )
    FROM warehouse w, inventory i
    WHERE w.warehouse_id = i.warehouse_id
    GROUP BY i.isbn
  ')
  let $warehouses := db2-fn:sqlquery('
    SELECT
        XMLAGG(
          XMLELEMENT(NAME "warehouse",        
            XMLFOREST(
              i.isbn AS "isbn",
              i.quantity AS "quantity",
              w.city AS "city",
              w.warehouse_id AS "id"
            ) 
          )
        )
    FROM warehouse w, inventory i      
    WHERE w.warehouse_id = i.warehouse_id
  ')[isbn=$total_order/isbn]
  return
    <book isbn="{$total_order/isbn}">
      <stock total="{$total_order/total}">
        {
          for $wh in $warehouses
          return 
            <warehouse id="{$wh/id}">
              <city>{$wh/city/text()}</city>
              <quantity>{$wh/quantity/text()}</quantity>
            </warehouse>
        }
      </stock>
    </book>   

就本例而言,示例输出可能会以如下所示的格式返回:

<book isbn="0201563177">
  <stock total="7">
    <warehouse id="1">
      <city>San Francisco</city>
      <quantity>2</quantity>
    </warehouse>
    <warehouse id="2">
      <city>San Jose</city>
      <quantity>5</quantity>
    </warehouse>
  </stock>
</book>  
<book isbn="0201633469">
  <stock total="4">
    <warehouse id="1">
      <city>San Francisco</city>
      <quantity>3</quantity>
    </warehouse>
    <warehouse id="2">
      <city>San Jose</city>
      <quantity>1</quantity>
    </warehouse>
  </stock>
</book>

分享这篇文章……

digg 将本文提交到 Digg
del.icio.us 发布到 del.icio.us
Slashdot 提交到 Slashdot!

结束语

本文展示了如何使用 WebSphere Federation Server 9.1 集成本地和远程 XML 存储数据。尽管还不能通过定义昵称来访问远程 XML 存储数据,但您看到了如何使用视图来实现这一目的。

当前,我们正致力于实现到远程 XML 存储数据的联邦访问。这不仅会削减本文中所描述的额外的配置,而且由于使用了直接访问而非视图,还会提高性能。此外,这个新的联邦访问会让您能够更新远程 XML 数据。我们坚信 pureXML 支持与联邦这一强大组合定会满足您不断变化的企业需求。

附录:配置脚本

A1. 填充书店示例

如果按 集成本地 XML 存储数据 一节中描述的那样建立了所需的表,就可以用数据填充这些表了。以下所示的代码行显示了 BOOKSTORE 表中的内容:

('0201633469', 
<book isbn="0201633469" year="1993" category="Computers">
  <title>TCP/IP Illustrated</title>
  <author>
    <last>Stevens</last>
    <first>W. Richard</first>
  </author>
  <publisher>Addison-Wesley Professional</publisher>
  <price>65.00</price>
</book>)
,
('0201563177', 
<book isbn="0201563177" year="1992" category="Computers">
  <title>Advanced Programming in the UNIX environment</title>
  <author>
    <last>Stevens</last>
    <first>W. Richard</first>
  </author>
  <publisher>Addison-Wesley Professional</publisher>
  <price>65.95</price>
</book>)

假设如下数据存储在 INVENTORY 表:

SELECT * FROM inventory;

INVENTORY_ID WAREHOUSE_ID ISBN       QUANTITY
------------ ------------ ---------- -----------
        1001            1 0201633469           3
        1002            1 0201563177           2
        1003            2 0201633469           1
        1004            2 0201563177           5

4 record(s) selected.


WAREHOUSE 表包含如下数据:

SELECT * FROM warehouse;

WAREHOUSE_ID STREET             CITY          STATE
------------ ------------------ ------------- -----------------
           2 4012 1st Street    San Jose      CA
           1 1234 Market Street San Francisco CA

2 record(s) selected.


AUTHOR 表被认定为空:

A2. 为分布式书店场景创建表

表示 BOOKSTORE 关系的 XML 文档存储于两个表内。第一个是本地 BOOKSTORE 表,驻留于 DB2 数据库服务器的联邦端。

CREATE TABLE bookstore1(isbn CHAR(10), xmlinfo XML);

另一个表位于 Oracle 10g Release 2 数据库。其定义如下:

CREATE TABLE bookstore2(isbn CHAR(10), xmlinfo XMLTYPE);

这两个数据库内的表通过相同的 XML 模式约束。

REVIEW 驻留于 MS SQL Server 2005 数据库,包含书的评论。 该表按如下所示定义:

CREATE TABLE review(review_id INT, xmlinfo XML);

CUSTOMER_INFO 存储于 DB2 9 数据库,包含客户信息。表定义如下所示:

CREATE TABLE customer_info(customer_id INT, xmlinfo XML);

INVENTORYWAREHOUSE 是非 XML 关系表,位于 DB2 9 数据库:

CREATE TABLE warehouse(warehouse_id INT, street CHAR(50), city CHAR(30), state CHAR(30));
CREATE TABLE inventory(inventory_id INT, warehouse_id INT, isbn CHAR(10), quantity INT);

在线订单信息位于本地文件系统的名为 orders.xml 的 XML 文档内。

A3.为分布式书店场景创建包装器、服务器和用户映射

我们需要定义 4 个包装器来访问 4 种不同类型的数据源:

CREATE WRAPPER net8;
CREATE WRAPPER drda;
CREATE WRAPPER mssqlodbc3;
CREATE WRAPPER xml_wrapper LIBRARY 'libdb2lsxml.a';
			

注意:我们的场景已经在 AIX 5.2 上测试过。

在包装器库用联邦系统注册过后,每个数据源需要被注册为服务器:

CREATE SERVER "oracle10g2" TYPE ORACLE VERSION 10.2
  WRAPPER net8 OPTIONS (NODE 'MYORA10');
 
CREATE SERVER "db2v91" TYPE db2/cs VERSION 9 
  WRAPPER drda AUTHORIZATION "myuser" PASSWORD "secret"
  OPTIONS (NODE 'MYDB2', DBNAME 'MYDB');

CREATE SERVER "mssql" TYPE MSSQLSERVER VERSION 2005 
  WRAPPER mssqlodbc3 OPTIONS (NODE 'MYMSSQL', DBNAME 'MYDB');

CREATE SERVER "xml_server" WRAPPER xml_wrapper;
			

接下来,可以创建用户映射以便在需要时将远程认证信息注册到数据源:

CREATE USER MAPPING FOR USER SERVER "oracle10g2"
  OPTIONS (REMOTE_AUTHID 'myuser', REMOTE_PASSWORD 'secret'); 

CREATE USER MAPPING FOR USER SERVER "db2v91"
  OPTIONS (REMOTE_AUTHID 'myuser', REMOTE_PASSWORD 'secret');

CREATE USER MAPPING FOR USER SERVER "mssql"
  OPTIONS (REMOTE_AUTHID 'myuser', REMOTE_PASSWORD 'secret'); 
			

A4. 填充分布式书店示例

按照 分布式书店场景 一节中的描述建立了所需的表后,就可以用数据填充这些表了。

联邦服务器上的 BOOKSTORE1 表包括如下数据:

% DB2 Federated Server
INSERT INTO bookstore1 VALUES('0201633469', 
'<book isbn="0201633469" year="1993" category="Computers">
  <title>TCP/IP Illustrated</title>
  <author>
    <last>Stevens</last>
    <first>W. Richard</first>
  </author>
  <publisher>Addison-Wesley Professional</publisher>
  <price>65.00</price>
</book>');

Oracle 10g Release 2 服务器上的 BOOKSTORE2 表由如下命令填充:

% Oracle 10g Release 2
INSERT INTO bookstore2 VALUES('0201563177', XMLTYPE(
'<book isbn="0201563177" year="1992" category="Computers">
  <title>Advanced Programming in the UNIX environment</title>
  <author>
    <last>Stevens</last>
    <first>W. Richard</first>
  </author>
  <publisher>Addison-Wesley Professional</publisher>
  <price>65.95</price>
</book>'));

驻留于 MS SQL Server 2005 的表 REVIEW 按如下所示填充:

INSERT INTO review VALUES
  (1, 
  '<reviews>
    <review id="10001" isbn="155860622X">A very good discussion of 
semi-structured database systems and XML.</review>
    <review id="10002" isbn="0201563177">A clear and detailed discussion 
of UNIX programming.</review>
    <review id="10003" isbn="0201633469">One of the best books on 
TCP/IP.</review>
  </reviews>');

数据通过如下命令插入到存储在 DB2 9 数据库中的 CUSTOMER_INFO 表:

INSERT INTO customer_info VALUES(1, XMLPARSE(DOCUMENT
'<customer id="1">
  <name><last>Smith</last><first>Joe</first></name>
  <address>
    <street>6127 Crown Bld</street>
    <city>San Jose</city>
    <state>CA</state>
  </address>
</customer>' PRESERVE WHITESPACE));

 INSERT INTO customer_info VALUES(2, XMLPARSE(DOCUMENT
'<customer id="2">
  <name><last>Miller</last><first>Bob</first></name>
  <address>
    <street>544 Capitol Expw</street>
    <city>San Jose</city><state>CA</state>
  </address>
</customer>' PRESERVE WHITESPACE));

INSERT INTO customer_info VALUES(3, XMLPARSE(DOCUMENT
'<customer id="3">
  <name><last>Meyer</last><first>Ann</first></name>
  <address>
    <street>8400 Main St</street>
    <city>San Francisco</city><state>CA</state>
  </address>
</customer>' PRESERVE WHITESPACE));

INSERT INTO customer_info VALUES(4, XMLPARSE(DOCUMENT
'<customer id="3">
  <name><last>Apple</last><first>Sue</first></name>
  <address>
    <street>2200 Diamond Blvd</street>
    <city>New York</city><state>NY</state>
  </address>
</customer>' PRESERVE WHITESPACE));

同一数据库上的 INVENTORYWAREHOUSE 表由以下数据填充:

INSERT INTO warehouse VALUES (1, '1234 Market Street', 'San Francisco', 'CA');
INSERT INTO warehouse VALUES (2, '4012 1st Street', 'San Jose', 'CA');
INSERT INTO inventory VALUES (1001, 1, '0201633469', 3);
INSERT INTO inventory VALUES (1002, 1, '0201563177', 2);
INSERT INTO inventory VALUES (1003, 2, '0201633469', 1);
INSERT INTO inventory VALUES (1004, 2, '0201563177', 5);

本地文件系统上的 XML 文档 orders.xml 内的在线订单信息包含如下数据:

<?xml version="1.0" encoding="UTF-8"?>
<orders>
  <order id="101" cid="1" date="2004-10-24">
    <item isbn="0201633469"/>    
    <item isbn="0201633469"/>    
  </order>
  <order id="102" cid="3" date="2004-10-25">
    <item isbn="0201633469"/>    
  </order>
  <order id="103" cid="2" date="2004-10-26">
    <item isbn="0201633469"/>    
    <item isbn="0201563177"/>    
  </order>
  <order id="104" cid="1" date="2004-10-27">
    <item isbn="0201563177"/>    
  </order>
  <order id="105" cid="3" date="2004-10-28">
    <item isbn="0201563177"/>    
    <item isbn="0201563177"/>    
  </order>
</orders>
			



参考资料

学习

获得产品和技术
  • 使用 IBM 试用软件 构建您的下一个开发项目,这些软件可以从 developerWorks 直接下载。


讨论


作者简介

Aakash Bordia 是坐落在加利福尼亚州圣何塞市的硅谷实验室的一名资深软件工程师。他于 2000 年 1 月毕业于 University of Illinois,之后,加入了 IBM DB2 Warehouse Manager 开发团队,致力于基于 SQL 的数据仓库转换的工作。在 2002 年,他转到了 WebSphere Information Integrator Federation 团队,在那里,他一直是一名编译器开发人员,最近他还负责开发团队代码的 QA 工作(即 QA 工程师)。


Dr. Eileen Lin 是坐落在加利福尼亚州圣何塞市的硅谷实验室的一名高级技术人员。她是负责 DataJoiner 的最早成员之一,DataJoiner 是一种联邦数据库产品,也是 DB2 中联邦技术的前驱。目前,她正担任 WebSphere Information Integrator 中这种技术的架构师。Dr. Lin 拥有很多专利,涵盖的领域有联邦技术、查询优化和并行查询处理等。


Ioana Ursu 是坐落在加利福尼亚州圣何塞市的硅谷实验室的一名高级软件工程师。她于 1998 年加入 IBM Almaden,从事 Garlic 研究项目方面的工作。从 1999 开始,她从事过联邦查询编译的很多领域,包括查询语义、查询重写、下推分析和查询优化。目前她在 WebSphere Information Integrator Federated Query Compiler 小组工作,主要从事通用联邦查询处理方面的工作。


Sebastian Hahnel 是坐落在加利福尼亚州圣何塞市的 IBM 硅谷实验室的一名实习软件工程师。在德国莱比锡应用科学大学完成计算机科学专业(荣誉毕业生)的学习之后,他于 2006 年 4 月加入了 WebSphere Information Integrator Federation 团队。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款