课程 6:查询 XML 数据

本课程描述如何使用 SQL 和/或 XQuery(使用 XQuery 表达式)来查询 XML 数据。

如果您仅使用 SQL,那么只能在列级别进行查询。 也就是说,可以返回存储在列中的整个 XML 文档,但不能在文档内进行查询或者返回文档片段。 要在 XML 文档内查询值或者返回文档片段,必须使用 XQuery。

本课程中的查询在 SQL 上下文中使用 XQuery,在 XQuery 上下文中使用 SQL。

要点: XQuery 区分大小写,但 SQL 不区分大小写。 因此,在使用 XQuery 时,指定诸如表名和 SQL 模式名(缺省情况下,这两个名称都是大写)之类的名称时一定要小心。 即使在 SQL 上下文中,XQuery 表达式仍将区分大小写。

在 SQL 上下文中查询

检索整个 XML 文档
要检索存储在名为 INFO 的列中的所有 XML 文档以及 CID 主键列中的值,请发出以下 SELECT 语句:
SELECT cid, info FROM customer~
此查询返回两个存储的 XML 文档。
检索和过滤 XML 值
要在 INFO 列的 XML 文档中查询,请发出以下 SELECT 语句,它将使用 XMLQUERY 函数来调用 XQuery 表达式:
SELECT XMLQUERY (
  'declare default element namespace "http://posample.org";
   for $d in $doc/customerinfo
   return <out>{$d/name}</out>'
   passing INFO as "doc") 
FROM Customer as c
WHERE XMLEXISTS ('declare default element namespace "http://posample.org";
   $i/customerinfo/addr[city="Toronto"]' passing c.INFO as "i")~

在 XMLQUERY 函数中,首先指定缺省名称空间。 此名称空间与先前插入的文档的名称空间匹配。 The for clause specifies iteration through the <customerinfo> elements in each document from the Info column. INFO 列是使用 passing 子句指定的,该子句将 INFO 列与 for 子句中引用的名为 doc 的变量绑定。 The return clause then constructs an <out> element, which contains the <name> element from each iteration of the for clause.

WHERE 子句使用 XMLEXISTS 谓词来仅考虑 INFO 列中的一部分文档。 此过滤仅生成 <city> 元素(沿指定的路径)的值为 Toronto 的那些文档。

此 SELECT 语句将返回以下已构造元素:
<out xmlns="http://posample.org"><name>Kathy Smith</name></out>
使用 db2-fn:sqlquery 时附带参数

要将值传递至 db2-fn:sqlquery 函数中的 SQL 全查询,请运行以下查询:

VALUES XMLQUERY (
  'declare default element namespace "http://posample.org";
  for $d in db2-fn:sqlquery(
    ''SELECT INFO FROM CUSTOMER WHERE Cid = parameter(1)'', 
    $testval)/customerinfo
  return <out>{$d/name}</out>'
  passing 1000 as "testval" )~

XMLQUERY 函数通过使用标识 testval 将值 1000 传递至 XQuery 表达式。 然后 XQuery 表达式通过使用 PARAMETER 标量函数将该值传递至 db2-fn:sqlquery 函数。

XQuery 表达式将返回以下已构造元素:

<out xmlns="http://posample.org">
   <name>Kathy Smith</name>
</out>

在 XQuery 上下文中查询

Db2® XQuery 提供了两个专门用于 Db2 数据库的内置函数: db2-fn:sqlquerydb2-fn:xmlcolumndb2-fn:sqlquery 检索作为 SQL 全查询的结果表的序列。 db2-fn:xmlcolumn 从 XML 列中检索序列。

如果查询直接调用 XQuery 表达式,那么必须在它前面添加不区分大小写的关键字 XQUERY。

注: 可以设置多个选项来定制命令行处理器环境,特别是用于显示 XQuery 表达式的结果。 例如,按如下所示设置 -i 选项,以便更容易阅读 XQuery 表达式的结果:
UPDATE COMMAND OPTIONS USING i ON~
检索整个 XML 文档
要检索先前插入到 INFO 列中的所有 XML 文档,可以将 XQuery 与 db2-fn:xmlcolumndb2-fn:sqlquery 配合使用。
使用 db2-fn:xmlcolumn
要检索 INFO 列中的所有 XML 文档,请运行以下查询:
XQUERY db2-fn:xmlcolumn ('CUSTOMER.INFO')~

缺省情况下,SQL 语句中的名称将自动转换为大写。 因此,当使用 CREATE TABLE SQL 语句创建了 CUSTOMER 表时,表名和列名都为大写。 因为 XQuery 区分大小写,所以在使用 db2-fn:xmlcolumn 指定表名和列名时必须使用正确的大小写。

此查询等价于 SQL 查询 SELECT Info FROM Customer

使用 db2-fn:sqlquery
要检索 INFO 列中的所有 XML 文档,请运行以下查询:
XQUERY db2-fn:sqlquery ('SELECT Info FROM Customer')~

您不必采用大写字母来指定 INFO 名称和 CUSTOMER 名称,这是因为 SELECT 语句是在 SQL 上下文中处理的,因此不区分大小写。

检索部分 XML 文档
除了检索整个 XML 文档之外,还可以通过将 XQuery 与 db2-fn:xmlcolumndb2-fn:sqlquery 配合使用来检索文档片段并过滤文档中存在的值。
使用 db2-fn:xmlcolumn
To return elements containing <name> nodes for all documents in the Info column that have a <city> element (along the path specified) with a value of Toronto, run the following query:
XQUERY declare default element namespace "http://posample.org"; 
  for $d in db2-fn:xmlcolumn('CUSTOMER.INFO')/customerinfo 
  where $d/addr/city="Toronto" 
  return <out>{$d/name}</out>~
db2-fn:xmlcolumn 函数从 CUSTOMER 表的 INFO 列中检索序列。 The for clause binds the variable $d to each <customerinfo> element in the CUSTOMER.INFO column. The where clause restricts the items to only those that have a <city> element (along the path specified) with a value of Toronto. return 子句将构造所返回的 XML 值。 This value is an element <out> that contains the <name> element for all documents that satisfy the condition specified in the where clause, as follows:
<out xmlns="http://posample.org">
<name>
              Kathy Smith
</name>
</out>
使用 db2-fn:sqlquery
要在 XQuery 表达式中发出全查询,请运行以下查询:
XQUERY declare default element namespace "http://posample.org";
  for $d in db2-fn:sqlquery(
    'SELECT INFO
     FROM CUSTOMER
     WHERE Cid < 2000')/customerinfo
  where $d/addr/city="Toronto"
  return <out>{$d/name}</out>~

在此示例中,首先在全查询中用非 XML CID 列中的特定值限制要被查询的 XML 文档集。 此示例说明了 db2-fn:sqlquery 的优点:它允许在 XQuery 表达式中应用 SQL 谓词。 The documents that result from the SQL query are then further restricted in the where clause of the XQuery expression to those documents that have a <city> element (along the path specified) with a value of Toronto.

此查询产生的结果与使用 db2-fn:xmlcolumn 的前一个示例产生的结果相同。
<out xmlns="http://posample.org">
<name>
              Kathy Smith
</name>
</out>
使用 db2-fn:sqlquery 时附带参数

要将值传递至 db2-fn:sqlquery 函数中的 SQL 全查询,请运行以下查询:

XQUERY declare default element namespace "http://posample.org";
  let $testval := 1000
  for $d in db2-fn:sqlquery(
    'SELECT INFO FROM CUSTOMER WHERE Cid = parameter(1)', 
    $testval)/customerinfo
  return <out>{$d/name}</out>~

在 XQuery 表达式中,let 子句将 $testval 的值设置为 1000。 然后,在 for 子句中,表达式会使用 PARAMETER 标量函数将该值传递至 db2-fn:sqlquery 函数。

XQuery 表达式将返回以下已构造元素:

<out xmlns="http://posample.org">
   <name>Kathy Smith</name>
</out>