我有一个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>
哪个保存在DB2数据库的XML列中。在/ a / element / @ name中是唯一的,/ b / element / @ name是唯一的等等。
现在我要在其中插入一个新的元素标记。如果已经存在具有相同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为null,这将使语句有效。但是,如果它不是空的,但只是缺少了呢?
答案 0 :(得分:1)
我找到了一个有效的解决方案,尽管它仍然感觉很尴尬。我想知道是否有更优雅的解决方案...
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
答案 1 :(得分:0)
您可以在XQuery表达式中添加if-then逻辑,根据存在的节点添加不同数量的XML。这种方法可以让您获得最大的灵活性,因为它可以编程来处理几乎任何可能的情况,例如where / data存在,而不是/ data / a。当根文档元素不是<data>
时,您甚至可以决定要做什么。
至于COALESCE(),我喜欢它并认为它是你所描述的条件的一个有价值的解决方法。