科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道使用XQuery查询DB2 XML数据

使用XQuery查询DB2 XML数据

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

DB2 将 XQuery 当作最好的语言,允许用户直接编写 XQuery 表达式,而不是将 XQueries 封装或嵌入到 SQL 语句中。而且,DB2 的查询引擎是在本地处理 XQueries。

来源:IT专家网 2008年6月5日

关键字: IBM 数据库 DB2

  • 评论
  • 分享微博
  • 分享邮件
过滤 XML 元素值

您可以修改上述 XQuery 例子,缩小选择范围。例如,我们来看看如何返回居住在邮政编码为 95116 的地区的所有客户的邮递地址。

与您想像的一样,通过 XQuery where 子句可以根据 XML 文档中 zip 元素的值来过滤结果。清单 10 说明了如何在 清单 8 中的 FLWOR 表达式中添加一个 where 子句,以获得您感兴趣的地址信息:

清单 10. 带有 “where” 子句的 FLWOR 表达式

xquery
for $y in db2-fn:xmlcolumn('CLIENTS.CONTACTINFO')/Client/Address
where $y/zip="95116"
return $y

这里添加的 where 子句很容易理解。for 子句依次将变量 $y 绑定到每个地址。where 子句包含一个小型的路径表达式,该表达式从每个地址向下定位到其内嵌的 zip 元素。只有当这个 zip 元素等于 95116 时,where 子句才为 true(相应的地址被保留)。

通过在路径表达式中添加一个谓词也可以得到相同的结果,如 清单 11 所示:

清单 11. 带附加过滤谓词的路径表达式

xquery
db2-fn:xmlcolumn('CLIENTS.CONTACTINFO')/Client/Address[zip="95116"]


当然,您可以根据邮政编码的值进行过滤,返回与街道地址无关的元素。而且,还可以在单个查询中根据多个 XML 元素值进行过滤。下面的查询返回居住在纽约市具有特定邮政编码(10011)的地区或圣何塞(San Jose)任何地方的客户的电子邮件信息。

清单 12. 在 FLWOR 表达式中根据多个 XML 元素值过滤


xquery
for $y in db2-fn:xmlcolumn('CLIENTS.CONTACTINFO')/Client
where $y/Address/zip="10011" or $y/Address/city="San Jose"
return $y/email

注意,我们更改了 for 子句,从而将变量 $y 绑定到 Client 元素,而不是绑定到 Address 元素。这样一来便可以根据 Client 元素的一部分子树(Address)过滤该元素,而返回另一部分子树(email)。where 子句和 return 子句中的路径表达式必须相对被绑定到变量(这里是 $y)的元素来编写。

通过路径表达式可以更简单地表达相同的查询:

清单 13. 使用路径表达式根据多个 XML 元素值进行过滤

xquery
db2-fn:xmlcolumn('CLIENTS.CONTACTINFO')/Client[Address/zip="10011"
or Address/city="San Jose"]/email;

仔细观察该查询的两种不同形式,其中比较隐蔽的一点是,与 SQL 程序员的预期相比,返回的结果在两个方面存在不同之处:
  1. 返回的结果中不包含那些符合条件但是没有提供电子邮件地址的客户的 XML 数据。换句话说,如果有 1000 个客户居住在圣河塞或邮政编码为 10011 的地区,其中有 700 个客户提供了电子邮件地址,那么返回的将是这 700 个电子邮件地址。这是由于前面提到的 XQuery 与 SQL 之间存在的基本差异 —— XQuery 不使用 null。
  2. 您无法知道哪些电子邮件地址来自同一个 XML 文档。换句话说,如果有 700 个居住在圣河塞或邮政编码为 10011 的地区的客户,并且每个客户提供了两个电子邮件地址,那么返回的结果是 1400 个 email 元素组成的列表。您得到的不是 一个包含 700 个记录、每个记录由两个电子邮件地址组成的序列。
这两点在某些情况下是可以的,在另外一些情况下又可能不可取。例如,如果需要通过电子邮件将一个通知发送给每个符合条件的有记录的帐户,那么很容易在应用程序中对 XML 格式的客户电子邮件地址列表进行迭代。然而,如果对每个客户只发送一次通知,包括那些没有提供街道地址的客户,那么上述 XQuery 就不能满足要求了。

有多种方法来修改这个查询,使返回的结果以某种方式表示缺失的信息,并且在有多个电子邮件地址来自相同客户记录(即相同的 XML 文档)的情况下作出说明。让我们简要地探索一下其中一种方法。不过,如果只是要检索一个列表,其中对于每个符合条件的客户包含一个电子邮件地址,那么只需对之前查询中的 return 子句略作修改:

清单 14. 只检索每个客户的第一个 email 元素

xquery
for $y in db2-fn:xmlcolumn('CLIENTS.CONTACTINFO')/Client
where $y/Address/zip="10011" or $y/Address/city="San Jose"
return $y/email[1]

该查询导致 DB2 返回它在每个符合条件的 XML 文档(客户联系方式记录)中找到的第一个电子邮件元素。如果对于一个符合条件的客户,DB2 没有找到电子邮件地址,那么对于这个客户就不返回任何信息。
转换 XML 输出

XQuery 的一个强大的方面是可以将 XML 输出从一种格式转换成另一种格式。例如,可以使用 XQuery 检索所有或部分存储的 XML 文档,并将输出转换成 HTML,以便在 Web 浏览器中显示。下面 清单 15 中的查询检索客户的地址,按照邮政编码对结果排序,并将输出转换成 XML 元素,作为一个无序的 HTML 列表中的一部分:

清单 15. 查询 DB2 XML 数据并以 HTML 格式返回结果

xquery
<ul> {
for $y in db2-fn:xmlcolumn('CLIENTS.CONTACTINFO')/Client/Address
order by $y/zip
return <li>{$y}</li>
} </ul>

该查询首先以 xquery 关键字开头,告诉 DB2 解析器 XQuery 是顶层语言。第二行将表示无序列表的 HTML 标记(<ul>)包括在结果中。它还包含本查询中使用的一对花括号中的左括号。花括号指示 DB2 计算和处理其中的表达式,而不是将其当作文字字符串。

第三行对客户地址进行迭代,依次将变量 $y 绑定到每个 address 元素。第四行包括一个新的 order by 子句,指出结果必须按照客户邮政编码(绑定到 $y 的每个 address 元素的 zip 子元素)升序排列。return 子句表明 Address 元素在返回之前要用 HTML 列表 item 标记括起来。最后一行结束查询,并结束 HTML 无序列表标记。

输出将类似 清单 16 所示:

清单 16. 上述查询的示例 HTML 输出

<ul>
<li>
<Address>
<street>9407 Los Gatos Blvd.</street>
<city>Los Gatos</city>
<state>CA</state>
<zip>95032</zip>
</Address>
</li>
<li>
<Address>
<street>4209 El Camino Real</street>
<city>Mountain View</city>
<state>CA</state>
<zip>95033</zip>
</Address>
</li>
. . .
</ul>

我们来考虑之前遇到的一个话题:当需要在返回结果中表明缺失的值,以及表明单个 XML 文档(例如单个客户记录)包含重复的元素(例如多个 email 地址)时,如何编写 XQuery。一种方法是将返回的输出封装在一个新的 XML 元素中,如下面 清单 17 中的查询所示:
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章