Создать путь с помощью xquery, если он не существует - PullRequest
1 голос
/ 28 июня 2011

У меня есть структура XML, которая выглядит следующим образом:

<data>
  <a>
    <element name="aName">123</element>
    <element name="xyz">foobar</element>
  </a>
  <b>
    <element name="aName">foo</element>
    <element name="otherName">bar</element>
  </b>
</data>

Который сохраняется в столбце XML в базе данных DB2. Внутри / a / element / @ name уникально, а / b / element / @ name уникально и т. Д.

Теперь я хочу вставить новый тег элемента либо в,. Если элемент с таким же атрибутом имени уже существует, я хочу заменить этот элемент (порядок тегов элемента не имеет значения). Я сделал это так:

update mytable set myXmlColumn=xmlquery('copy $new := $old modify
  (
    do delete $new/data/a/element[@name=$newName],
    do insert $insert as last into $new/data/a
  ) return $new'
  passing
    'aName' as "newName",
    xmlparse(document '<element name="aName">aaa</element>') as "insert"),
    myXmlColumn as "old"
) where id=123

При этом новый элемент вставляется правильно, удаляя другой элемент с тем же именем, если он существовал. Но знайте, я хочу, чтобы это работало, даже если тег еще не существует (в этом случае должен быть создан пустой тег и добавлен новый элемент), и он все равно должен работать, если myXmlColumn ранее был нулевым.

Для последнего требования я нашел решение, хотя оно кажется мне довольно не элегантным: в проходящем разделе я могу написать coalesce(myXmlColumn,xmlparse(document '<data><a /></data>')), который заставит оператор работать, если myXmlColumn равен нулю. Но что, если он не нулевой, а просто отсутствует?

Ответы [ 2 ]

1 голос
/ 28 июня 2011

Я нашел решение, которое работает, хотя все еще чувствует себя неловко.Интересно, есть ли более элегантное решение ...

update mytable set myXmlColumn=xmlquery('copy $xml := (if (not($xml/data/a)) then transform copy $xml := $xml modify (do insert <a/> as last into $xml/data) return $xml else $xml) modify
  (
    do delete $xml/data/a/element[@name=$newName],
    do insert $insert as last into $xml/data/a
  ) return $xml'
  passing
    'aName' as "newName",
    xmlparse(document '<element name="aName">aaa</element>') as "insert"),
    COALESCE(myXmlColumn, xmlparse(document '<data/>')) as "xml"
) where id=123
0 голосов
/ 28 июня 2011

Вы можете добавить логику if-then в свое выражение XQuery, которое будет добавлять различное количество XML в зависимости от того, какие узлы существуют. Такой подход обеспечивает максимальную гибкость, поскольку он может быть запрограммирован для обработки практически любой возможной ситуации, например, где / data существует, но не / data / a. Вы даже можете решить, что делать, если корневым элементом документа не является <data>.

Что касается COALESCE (), мне это нравится, и я считаю, что это достойный обходной путь для описанного вами состояния.

...