将MERGE与XMLQUERY一起使用并进行转换

时间:2013-04-25 14:42:21

标签: merge db2 xquery

使用DB2 LUW 10.1。我无法使用MERGE处理两个使用XQUERY转换合并的XML列的表。

我有一个看起来像这样的表:

create table foo (
  id int not null primary key,
  data xml not null
)

要将数据导入此表,我将其(使用LOAD)加载到如下所示的临时表中:

create table foo_incoming (
  id int not null,
  data xml not null
)

使用XQUERY转换合并XML列中的数据。它背后有一些逻辑,所以它并不简单,但也不过分复杂。我已经使用手动UPDATE测试了转换,所以我知道它有效。

然后我尝试合并这两个表:

merge into foo f
  using (select * from foo_incoming) i
  on (f.id = i.id)
  when matched then
    update set data = xmlquery('
        transform
          copy $out := $old
          modify ( ... )
          return $out'
        passing f.data as "old", i.data as "new")
  when not matched then
    insert (id, data) values (i.id, i.data)

当foo中有数据时,这非常有效。 XML列完全按照我希望的方式合并。但如果foo为空,我会收到此错误:

SQL16084N  An assigned value in the copy clause of a transform expression is
not a sequence with exactly one item that is a node. Error QName=err:XUTY0013.
SQLSTATE=10705

似乎DB2正在尝试评估XQUERY,即使合并不匹配。因此,f.data为NULL,并且转换中的复制表达式获得空序列。如果我删除整个“匹配时”子句,则该语句可以正常工作。

我做错了什么?或者这是DB2的MERGE语句的限制吗?


我试图通过将简单的“匹配时”更改为“匹配时和(f.data不为空)”之类的东西来解决这个问题,但这没有效果。我也尝试将XQUERY表达式更改为:

if($old)
then
  transform
    copy $out := $old
    ...
else ()

这也没有帮助。我发现的唯一解决方法是将MERGE分成两部分。首先,我会这样做,以更新foo和foo_incoming中的行:

merge into foo f
  using
    (
      select q1.id, q1.data
        from foo_incoming q1 inner join foo q2
          on (q1.id = q2.id)
    ) i
  on (f.id = i.id)
  when matched then udpate ...;

然后,插入foo_incoming但不是foo的行:

merge into foo f
  using
    (
      select q1.id, q1.data
        from foo_incoming q1 left outer join foo q2
          on (q1.id = q2.id)
        where q2.id is null
    ) i
  on (f.id = i.id)
  when not matched then insert ...;

这很有效。不过,我希望表现糟透了。这就是我通常将其解释为一种警示标志,即我的思维中存在一个根本性的错误。

1 个答案:

答案 0 :(得分:1)

这可能是DB2中应该修复的错误。这里已经描述和讨论了同样的问题:

https://www.ibm.com/developerworks/community/forums/html/topic?id=02fb0ba7-249d-431a-b173-e70511d3b582&ps=25

我希望即将推出的DB2 fixpack可以解决这个问题。