通过路径表达式可以更简单地表达相同的查询:
清单 13. 使用路径表达式根据多个 XML 元素值进行过滤
xquery
db2-fn:xmlcolumn('CLIENTS.CONTACTINFO')/Client[Address/zip="10011"
or Address/city="San Jose"]/email;
|
仔细观察该查询的两种不同形式,其中比较隐蔽的一点是,与 SQL 程序员的预期相比,返回的结果在两个方面存在不同之处:
- 返回的结果中不包含那些符合条件但是没有提供电子邮件地址的客户的 XML 数据。换句话说,如果有 1000 个客户居住在圣河塞或邮政编码为 10011 的地区,其中有 700 个客户提供了电子邮件地址,那么返回的将是这 700 个电子邮件地址。这是由于前面提到的 XQuery 与 SQL 之间存在的基本差异 —— XQuery 不使用 null。
- 您无法知道哪些电子邮件地址来自同一个 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 中的查询所示:

发表评论