将当前值复制到文本编辑器,对其进行修改,然后尝试使用新字符串更新值会很痛苦。如果超过 4000 个字符(如果您使用 CLOB 进行存储,这很可能),您将不得不在 PL/SQL 中进行;如果超过 32K,您将不得不分块创建和更新一个临时 CLOB,这意味着拆分您的字符串。
不过,如果先将 CLOB 转换为 XMLType,则可以通过 SQL 来完成。您可以为此使用the updatexml function,并使用合适的 XPath 参数来匹配您感兴趣的行和属性:
select updatexml(xmltype(t.xmldata), '//item[@code="00000012"]/@code', '00000011').getclobval()
from tablex t
where dbms_lob.compare(xmldata, empty_clob()) != 0
and xmlexists('//item[@code="00000012"]' passing xmltype(xmldata));
UPDATEXML(XMLTYPE(T.XMLDATA),'//ITEM[@CODE="00000012"]/@CODE','00000011')
--------------------------------------------------------------------------------
<ExampleMapping><item code="00000011" name="Test1"/><item code="00000013" name="Test2"/></ExampleMapping>
我使用了您的字符串的修改版本,删除了每个“名称”之前的额外“项目”,以使其成为有效的 XML。我还将结果转换回 CLOB,因为您的客户端似乎无法处理 XMLType。
更新表格中的行而不是仅仅选择它:
update tablex
set xmldata = updatexml(xmltype(xmldata), '//item[@code="00000012"]/@code', '00000011').getclobval()
where dbms_lob.compare(xmldata, empty_clob()) != 0
and xmlexists('//item[@code="00000012"]' passing xmltype(xmldata));
1 row updated.
select * from tablex;
ID XMLDATA
---------- ---------------------------------------------------------------------
1 <ExampleMapping><item code="00000011" name="Test1"/><item code="00000013" name="Test2"/></ExampleMapping>
2 <ExampleMapping><item code="00000014" name="Test3"/><item code="00000015" name="Test4"/></ExampleMapping>
3
4
这使用xmlexists 仅将更新应用于匹配的行,因此您不会触及实际上不需要更改的行。我的虚拟表中有四行,其中一行为空,另一行为empty_clob(必须用the dbms_lob.compare 排除);但只更新了一行。
要完全删除项目,请使用the deletexml function:
update tablex
set xmldata = deletexml(xmltype(xmldata), '//item[@code="00000014"]').getclobval()
where dbms_lob.compare(xmldata, empty_clob()) != 0
and xmlexists('//item[@code="00000014"]' passing xmltype(xmldata));
1 row updated.
select * from tablex;
ID XMLDATA
---------- ---------------------------------------------------------------------
1 <ExampleMapping><item code="00000011" name="Test1"/><item code="00000013" name="Test2"/></ExampleMapping>
2 <ExampleMapping><item code="00000015" name="Test4"/></ExampleMapping>
3
4
如果您想匹配多个属性(在您的评论中不清楚),您可以在 XPath 中使用 and:'//item[@code="00000014" and @name="Test3"]'(在这两个地方)。我也懒惰使用//item;最好使用完整路径,/ExampleMapping/item[...]。
阅读有关操作 XML 的更多信息in the documentation。