0

DB2 LUW 10.1 を使用。XQUERY 変換を使用してマージされた XML 列を持つ 2 つのテーブルで MERGE を機能させるのに問題があります。

次のようなテーブルがあります。

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 変換を使用してマージされます。その背後にはいくつかのロジックがあるため、簡単ではありませんが、過度に複雑でもありません。手動の UPDATE を使用して変換をテストしたので、動作することがわかりました。

次に、次のように 2 つのテーブルをマージしようとします。

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 is not null)」のようなものに変更することでこれを回避しようとしましたが、効果はありません。また、XQUERY 式を次のように変更してみました。

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

それも役に立ちませんでした。私が見つけた唯一の回避策は、MERGE を 2 つに分割することです。まず、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 ...;

これは機能します。ただし、パフォーマンスはひどいものになると思います。そして、これは私が通常、私の思考に根本的な誤りがあるという警告サインとして解釈する一種のハッキングです.

4

1 に答える 1

1

これは、修正が必要な DB2 のバグである可能性があります。同じ問題がここで説明および議論されています。

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

今後の DB2 フィックスパックで問題が解決されることを願っています。

于 2013-08-07T04:38:51.357 に答える