DB2 将 XQuery 当作最好的语言,允许用户直接编写 XQuery 表达式,而不是将 XQueries 封装或嵌入到 SQL 语句中。而且,DB2 的查询引擎是在本地处理 XQueries。
清单 17. 在 XQuery 结果中表明缺失的值和重复的元素
xquery for $y in db2-fn:xmlcolumn('CLIENTS.CONTACTINFO')/Client where $y/Address[zip="10011"] or $y/Address[city="San Jose"] return <emailList> {$y/email} </emailList>
|
该查询将返回一个 “emailList” 元素序列,每个符合条件的客户记录对应一个元素。每个 emailList 元素将包含 e-mail 数据。如果 DB2 在客户的记录中只发现一个 e-mail 地址,它将返回那个元素和它的值。如果 DB2 发现多个 e-mail 地址,它将返回所有 e-mail 元素和它们的值。最后,如果 DB2 没有发现 e-mail 地址,那么它将返回一个空的 emailList 元素。因此,输出如下所示:
清单 18. 上述查询的示例输出
<emailList> <email>love2shop@yahoo.com</email> </emailList> <emailList/> <emailList> <email>beatlesfan36@hotmail.com</email> <email>lennonfan36@hotmail.com</email> </emailList> . . .
|
使用条件逻辑 XQuery 的 XML 输出转换功能可以与它内置的对条件逻辑的支持相结合,以减少应用程序代码的复杂性。“items” 表中包括一个 XML 列,该列包含客户对产品作出的评论。有些客户要求对他们的评论作出响应,对于这些用户,需要创建新的 “action” 元素,其中包含产品 ID、客户 ID 和评语,以便将这些信息发送给适当的个人进行处理。但是,那些不要求响应的评论在商业上也是非常重要的信息,您不想忽视它们。所以,创建一个 “info” 元素,其中只包含产品 ID 和评语。下面展示了如何使用 XQuery if-then-else 表达式来完成这项任务:
清单 19. 在 XQuery 中使用 “if-then-else” 表达式
xquery for $y in db2-fn:xmlcolumn('ITEMS.COMMENTS')/Comments/Comment return ( if ($y/ResponseRequested = 'Yes') then <action> {$y/ProductID, $y/CustomerID, $y/Message} </action> else ( <info> {$y/ProductID, $y/Message} </info> ) )
|
现在您应该对这个查询的大部分感到熟悉,所以我们只关注条件逻辑。if 子句判断一条给定评论的 ResponseRequested 子元素的值是否等于 “Yes”。如果是,那么执行 then 子句,导致 DB2 返回一个新元素(“action”),其中包含三个子元素:ProductID、CustomerID 和 Message。否则,执行 else 子句,DB2 返回一个 “info” 元素,其中只包含产品 ID 和评语数据。
使用 “let” 子句
您已经看到了如何使用 FLWOR 表达式的所有部分,除了一个部分:let 子句。该子句用于将一个值(可能包含一个由多项组成的列表)赋给一个变量,这个变量可以在 FLWOR 表达式的其他子句中使用。
假设您想得到一份列表,统计出每种产品收到的评论数量。那么可以使用以下查询:
清单 20. 使用 “let” 子句
xquery for $p in distinct-values (db2-fn:xmlcolumn('ITEMS.COMMENTS')/Comments/Comment/ProductID) let $pc := db2-fn:xmlcolumn('ITEMS.COMMENTS') /Comments/Comment[ProductID = $p] return <product> <id> { $p } </id> <comments> { count($pc) } </comments> </product>
|
for 子句中的 distinct-values 函数返回一个列表,其中包含在 ITEMS 表的 COMMENTS 列中的所有 Comment 中发现的所有不同的 ProductID 值。for 子句依次将变量 $p 绑定到每个 ProductID 值。对于 $p 的每个值,let 子句再次扫描 ITEMS 列,并将变量 $pc 绑定到一个列表,列表中包含所有 ProductID 与 $p 中的 ProductID 相匹配的评论。return 子句为每个不同的 ProductID 值构造一个新的 “product” 元素。每个 “product” 元素包含两个子元素:一个包含 ProductID 值的 “id” 元素,和一个包含给定产品上所收到的评论的数量的 “comments” 元素。
这个例子查询的结果如下:
清单 21. 上述查询的示例输出
<product> <id>3926</id> <comments>28</comments> </product> <product> <id>4097</id> <comments>13</comments> </product>
|