这个例子查询的结果如下:
清单 21. 上述查询的示例输出
<product>
<id>3926</id>
<comments>28</comments>
</product>
<product>
<id>4097</id>
<comments>13</comments>
</product>
|
带嵌入式 SQL 的 XQueries
至此,您已经看到了如何编写 XQuery 来检索 XML 文档片段,创建新格式的 XML 输出,以及根据查询中指定的条件返回不同的输出。简言之,您已经学会了使用 XQuery 查询存储在
DB2 中的 XML 数据的几种方法。
显然,除了本文介绍的内容外,关于 XQuery 还有更多要学的东西。但是我们不能忽略了我们还没有讲到的一个大话题:如何在 XQuery 中嵌入 SQL。如果需要编写根据 XML 和非 XML 列的值过滤数据的查询,那么这样做很有用。
您可能还记得,文章 “用 SQL 查询
DB2 XML 数据” 描述了如何将简单的 XQuery 表达式嵌入在 SQL 语句中,以便完成这样的任务。这里,我们来看看如何反过来做:将 SQL 嵌入在 XQuery 中,从而根据传统的 SQL 数据值和特定的 XML 元素值对结果进行限制。
您可以使用 db2-fn:sqlquery 函数替代 db2-fn:xmlcolumn 函数,后者返回一个表的一个列中所有 XML 数据,而前者执行一个 SQL 查询,并且只返回所选择的数据。传递给 db2-fn:sqlquery 函数的 SQL 查询必须返回 XML 数据。然后 XQuery 可以进一步处理这种 XML 数据。
清单 22 中的查询检索关于评论的信息,评论所涉及的产品是建议零售价("srp")大于 $100 的产品,并且在评论中客户请求响应。您应该记得,价格数据存储在一个十进制数类型的 SQL 列中,而客户评论则存储为 XML。对于存储在数据库中的每条符合条件的评论,返回的数据(包括产品 ID、客户 ID 和客户评论)被包括在一个 XML “action” 元素中。
清单 22. 将 SQL 嵌入在 XQuery 中
xquery
for $y in
db2-fn:sqlquery('select comments from items where srp > 100')/Comments/Comment
where $y/ResponseRequested="Yes"
return (
<action>
{$y/ProductID,
$y/CustomerID,
$y/Message}
</action>
)
|
同样,这个查询的大部分对于您来说应该比较熟悉了,所以我们只关注这里出现的新函数:db2-fn:sqlquery。
DB2 处理提供给该函数的 SQL SELECT 语句,以确定哪些行包含关于定价超过 $100 的产品的信息。存储在这些行中的文档作为一个路径表达式的输出,该路径表达式返回所有内嵌的 Comment 元素。该查询中随后的部分使用 XQuery where 子句进一步过滤返回的数据,并将选中的评论的一些部分转换成新的 XML 片段。
清楚这些之后,让我们考虑如何解决一个稍微不同的问题。假设您需要一份列表,其中包含居住在圣河塞的 “Gold” 客户的所有 e-mail 地址。而且,如果一个客户有多个 e-mail 地址,那么您希望将这些 e-mail 地址都包括在输出中,作为单个客户记录的一部分。最后,如果某个符合条件的 “Gold” 客户没有提供 e-mail 地址,那么需要检索他或她的邮递地址。清单 23 展示了编写该查询的一种方法:
清单 23. 将 SQL 嵌入在包含条件逻辑的 XQuery 中
xquery
for $y in
db2-fn:sqlquery('select contactinfo from clients where status=''Gold'' ')/Client
where $y/Address/city="San Jose"
return (
if ($y/email) then <emailList>{$y/email}</emailList>
else $y/Address
)
|
这个查询有两个方面要解释一下。首先,嵌入在第二行的 SELECT 语句包含一个基于 “status” 列的查询谓词,它将这个 VARCHAR 列与字符串 "Gold" 相比较。在 SQL 中,这样的字符串放在单引号里面。注意,虽然这个例子看上去使用了双引号,但实际上它是在比较值("Gold")前后使用了两个单引号。“额外” 的那个单引号是换码符。如果在基于字符串的查询谓词周围使用双引号,而不是单引号,就会收到语法错误。

发表评论