我有一些示例代码如下:
WITH xtbl AS
(SELECT 1 AS xtbl_id,
xmltype ('<node_root>
<node_1>12</node_1>
<node_2>233</node_2>
<node_3>223</node_3>
<node_4>234</node_4>
</node_root>') AS x
FROM Dual
UNION ALL
SELECT 2, xmltype ('<node_root>
<node_1></node_1>
<node_2>233</node_2>
<node_3>223</node_3>
<node_4>234</node_4>
</node_root>')
FROM Dual)
SELECT xtbl_id,
x,
Updatexml (x,
'/node_root/node_2',
NULL,
'/node_root/node_3',
NULL,
'/node_root/node_4',
NULL)
AS xcol
FROM xtbl
WHERE (SELECT node_1
FROM Xmltable ('node_root'
PASSING x
COLUMNS node_1 INTEGER PATH 'node_1'))
IS NOT NULL;
我的要求是,当/node_root/node_1
列中的x
不为空时,请将/node_root/node_2
,/node_root/node_3
和/node_root/node_4
的值替换为null。我在Updatexml
查询中使用的SELECT
函数也是如此。
这里的问题是Updatexml
在Oracle 12c中不起作用。这就是我在子查询中使用Xmltable
的原因,它在过滤数据方面非常有效,但是我无法用null替换节点值。
我尝试查看Oracle Docs的XQuery,但无法理解它如何有助于替换节点值。
请提供一个描述性的例子。
答案 0 :(得分:2)
Oracle文档recommends to use XQuery to update XML。所以首先要尝试。
首先,有可能采用旧方法和功能。可以使用下面的XQuery代替调用XmlUpdate
:
XMLQuery(
'
declare function local:copy-replace($element as element()) {
if ($element/self::node_2) then <node_2/>
else if ($element/self::node_3) then <node_3/>
else if ($element/self::node_4) then <node_4/>
else element {node-name($element)}
{$element/@*,
for $child in $element/node()
return if ($child instance of element())
then local:copy-replace($child)
else $child
}
};
local:copy-replace($p/*)
'
passing x as "p" returning content
) as xcol_2
另一种更短更直观的变体:
XMLQuery(
'
copy $p2 := $p
modify(
replace value of node $p2/node_root/node_2 with "",
replace value of node $p2/node_root/node_3 with "",
replace value of node $p2/node_root/node_4 with ""
)
return $p2
'
passing x as "p" returning content
) as xcol_3
此外,只有在条件不匹配时才可以返回修改后的XML值:
WITH xtbl AS
(SELECT 1 AS xtbl_id,
xmltype ('<node_root>
<node_1>12</node_1>
<node_2>233</node_2>
<node_3>223</node_3>
<node_4>234</node_4>
</node_root>') AS x
FROM Dual
UNION ALL
SELECT 2, xmltype ('<node_root>
<node_1></node_1>
<node_2>233</node_2>
<node_3>223</node_3>
<node_4>234</node_4>
</node_root>')
FROM Dual)
SELECT xtbl_id,
x,
XMLQuery(
'
for $test in $p/*
return
if( empty($p/node_root/node_1/text()) )
then $p
else (
copy $p2 := $p
modify(
replace value of node $p2/node_root/node_2 with "",
replace value of node $p2/node_root/node_3 with "",
replace value of node $p2/node_root/node_4 with ""
)
return $p2
)
'
passing x as "p" returning content
) as xcol_4
FROM xtbl
因此,有许多变体可以对XML值执行操作,但这需要更深入的XQuery和XPath知识,而不是相对简单的XmlUpdate函数......