编辑 XML 存储为 CLOB

Edit XML stored as CLOB

我有一个很长的 XML 文档作为 CLOB 类型存储在 Oracle 数据库中。在我的 SQL 工具中,我什至无法复制出完整的 XML 数据,因为它太长了(我只能复制出 XML 的一部分)。

假设我想将项目代码=“00000012”编辑为“00000011”,我该怎么做?

我的逻辑是从 CLOB 列中提取整个 XML 内容,在文本编辑器中修改它,然后使用查询更新它。

以下是我的XML的简短表示,在数据库中的大小更大。

<ExampleMapping><item code="00000012" item name="Test1"/><item code="00000013" item name="Test2"/></ExampleMapping>  

在我的数据库中,table 名称是 TableX,列是 IDxmlData

将当前值复制到文本编辑器,对其进行修改,然后尝试使用新字符串更新值将会很痛苦。如果超过 4000 个字符(如果您使用 CLOB 进行存储,则很可能),则必须在 PL/SQL 中执行;如果超过 32K,则必须以块的形式创建和更新临时 CLOB,这意味着将字符串拆分。

不过,如果您先将 CLOB 转换为 XMLType,则可以通过 SQL 完成此操作。您可以为此使用 the updatexml function,使用 suitable 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>

我使用了您的字符串的修改版本,删除了每个 'name' 之前的额外 'item' 以使其有效 XML。我还将结果转换回 CLOB,因为您的客户端似乎无法处理 XMLType.

要更新 table 中的行,而不仅仅是选择它:

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 仅将更新应用于匹配的行,因此您不会触及实际上不需要更改的行。我的虚拟 table 中有四行,其中一行为空,另一行为 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.