使用 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
)
XML 列中的数据使用 XQUERY 转换进行合并。它背后有一些逻辑,所以它并不简单,但也不是太复杂。我已经使用手动更新测试了转换,所以我知道它有效。
然后我尝试像这样合并两个表:
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 ...;
这行得通。然而,我预计表现会很糟糕。这是我通常解释为警告信号的那种黑客行为,表明我的想法存在根本性错误。