DB2 V9.7 for Linux, UNIX, and Windows

在变换表达式中使用更新操作

必须在变换表达式的 modify 子句中使用 DB2® XQuery 更新表达式。更新表达式会作用于变换表达式 copy 子句创建的复制节点。

下列表达式是更新表达式:

  • 删除表达式
  • 插入表达式
  • 重命名表达式
  • 替换表达式
  • 其 return 子句包含更新表达式的 FLWOR 表达式
  • 其 then 或 else 子句包含更新表达式的条件表达式
  • 用逗号隔开的两个或更多更新表达式,其中所有操作数都是更新表达式或空序列

DB2 XQuery 会对无效更新表达式返回错误。例如,如果条件表达式的一个分支包含更新表达式,而另一个分支包含并非空序列的非更新表达式,那么 DB2 XQuery 会返回错误。

变换表达式并非更新表达式,原因是它不会修改任何现有节点。变换表达式会创建现有节点的修改副本。变换表达式的结果可能包括通过更新变换表达式 modify 子句中的表达式创建的节点以及先前存在的节点。

处理 XQuery 更新操作

在变换表达式中,modify 子句可指定多个更新。例如,modify 子句可包含两个更新表达式,一个表达式用于替换现有值,另一个表达式用于插入新元素。modify 子句包含多个更新表达式时,每个更新表达式会独立求值,并生成由变换表达式 copy 子句创建的特定节点的关联更改操作列表。

在 modify 子句中,更新表达式不能修改由其他更新表达式添加的新节点。例如,如果一个更新表达式添加了新的元素节点,那么另一个更新表达式不能更改新创建节点的名称。

变换表达式 modify 子句中指定的所有更改操作会被收集到一起,并按以下顺序进行有效应用:
  1. 下列更新操作是按不确定的顺序执行的:
    • 未使用 before、after、as first 或 as last 之类的排序关键字的插入操作。
    • 所有重命名操作。
    • 替换操作,其中指定了关键字 value of 并且目标节点为属性、文本、注释或处理指令节点。
  2. 使用 before、after、as first 或 as last 之类的排序关键字的插入操作。
  3. 未指定关键字 value of 的替换操作。
  4. 替换操作,其中指定了关键字 value of 并且目标节点为元素节点。
  5. 所有删除操作。

应用更改操作的顺序应确保一系列多个更改将生成确定的结果。有关更新操作的执行顺序如何保证一系列多个更改生成确定结果的示例,请参阅示例中的最后一个 XQuery 表达式。

无效 XQuery 更新操作

处理变换表达式期间,如果出现下列其中一种情况,那么 DB2 XQuery 会返回错误:
  • 对同一节点应用了两个或更多重命名操作。
  • 对同一节点应用了使用关键字 value of 的两个或更多替换操作。
  • 对同一节点应用了未使用关键字 value of 的两个或更多替换操作。
  • 变换表达式的结果并非有效 XDM 实例。

    包含的元素的两个属性同名就是一个无效 XDM 实例的示例。

  • XDM 实例包含不一致的名称空间绑定。

    下面是不一致的名称空间绑定的示例:

    • 属性节点的 QName 中的名称空间绑定与其父元素节点中的名称空间绑定不一致。
    • 具有同一父代的两个属性节点中的名称空间绑定相互不一致。

示例

在以下示例中,变换表达式的 copy 子句将变量 $product 绑定至元素节点的副本,而变换表达式的 modify 子句使用两个更新表达式来更改复制节点:

xquery
transform
copy $product := db2-fn:sqlquery(
  "select description from product where pid='100-100-01'")/product
modify(
  do replace value of $product/description/price with 349.95,
  do insert <status>Available</status> as last into $product )
return $product

以下示例在 SQL UPDATE 语句中使用 XQuery 变换表达式来修改 CUSTOMER 表中的 XML 数据。SQL UPDATE 语句会作用于 CUSTOMER 表的某行。变换表达式会根据该行的 INFO 列创建 XML 文档的副本,并将 status 元素添加至文档副本。UPDATE 语句会将该行 INFO 列中的文档替换为变换表达式修改后的文档副本:

UPDATE customer
SET info = xmlquery( 'transform
   copy $newinfo := $info
   modify do insert <status>Current</status> as last into $newinfo/customerinfo
   return $newinfo' passing info as "info")
WHERE cid = 1003

以下示例使用 DB2 SAMPLE 数据库中的 CUSTOMER 表。在 CUSTOMER 表中,XML 列 INFO 包含客户地址和电话信息。

在以下示例中,SQL SELECT 语句会作用于 CUSTOMER 表的某行。变换表达式的 copy 子句会根据列 INFO 创建 XML 文档的副本。删除表达式会删除文档副本中的地址信息和非工作电话号码。return 会使用 CUSTOMER 表的原始文档中的客户标识属性和国家或地区属性:
SELECT XMLQUERY( 'transform
  copy $mycust := $d
  modify
    do delete ( $mycust/customerinfo/addr, 
       $mycust/customerinfo/phone[@type != "work"] )
  return
  <custinfo>
    <Cid>{data($d/customerinfo/@Cid)}</Cid>
    {$mycust/customerinfo/*}
    <country>{data($d/customerinfo/addr/@country)}</country>
  </custinfo>'
  passing INFO as "d")
FROM CUSTOMER
WHERE CID = 1003

对 SAMPLE 数据库运行时,该语句将返回以下结果:

<custinfo>
  <Cid>1003</Cid>
    <name>Robert Shoemaker</name>
    <phone type="work">905-555-7258</phone>
  <country>Canada</country>
</custinfo>

在以下示例中,XQuery 表达式会说明更新操作的顺序如何保证一系列多个更改将生成确定的结果。插入表达式会在 phone 元素后添加 status 元素,而替换表达式会将 phone 元素替换为 email 元素:

xquery
let $email  := <email>jnoodle@my-email.com</email>
let $status := <status>current</status>
return
  transform
  copy $mycust := db2-fn:sqlquery('select info from customer where cid = 1002')
  modify (
    do replace $mycust/customerinfo/phone with $email,
    do insert $status after $mycust/customerinfo/phone[@type = "work"] )
  return $mycust

在 modify 子句中,替换表达式在插入表达式之前。但是,更新复制节点序列 $mycust 时,会在替换更新操作之前执行插入更新操作,以确保生成确定的结果。对 SAMPLE 数据库运行时,该表达式将返回以下结果:

<customerinfo Cid="1002">
  <name>Jim Noodle</name>
  <addr country="Canada">
    <street>25 EastCreek</street>
    <city>Markham</city>
    <prov-state>Ontario</prov-state>
    <pcode-zip>N9C 3T6</pcode-zip>
  </addr>
  <email>jnoodle@my-email.com</email>
  <status>current</status>
</customerinfo>

如果先执行替换操作,那么 phone 元素不会在节点序列中,而用于在 phone 元素后插入 status 元素的操作没有任何意义。

有关更新操作的顺序的信息,请参阅处理 XQuery 更新操作。

父主题: 更新 XML 数据
父主题: 变换表达式和更新表达式
相关参考:
删除表达式
插入表达式
PARAMETER 标量函数
重命名表达式
替换表达式
变换表达式
UPDATE 语句