编辑存储为CLOB的XML

时间:2015-08-04 03:42:04

标签: sql xml oracle clob

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

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

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

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

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

在我的数据库中,表名为TableX,列为IDxmlData

1 个答案:

答案 0 :(得分:0)

将当前值复制到文本编辑器,修改它,然后尝试使用新字符串更新值将会很痛苦。如果它超过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>

我已经使用了字符串的修改版本,删除了额外的&#39;项目&#39;在每个名字之前&#39;使它成为有效的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的更多信息。