编辑 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
,列是 ID
和 xmlData
。
将当前值复制到文本编辑器,对其进行修改,然后尝试使用新字符串更新值将会很痛苦。如果超过 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.
我有一个很长的 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
,列是 ID
和 xmlData
。
将当前值复制到文本编辑器,对其进行修改,然后尝试使用新字符串更新值将会很痛苦。如果超过 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.