我有一个非常长的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
,列为ID
和xmlData
。
答案 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的更多信息。