【问题标题】:Edit XML stored as CLOB编辑存储为 CLOB 的 XML
【发布时间】:2015-08-04 03:42:03
【问题描述】:

我有一个很长的 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>  

在我的数据库中,表名是TableX,列是ID 和xmlData。

【问题讨论】:

    标签: sql xml oracle clob


    【解决方案1】:

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

    【讨论】:

    • 您好,首先感谢您的回复。我尝试了第二种方法来更新我的 xml,但在 xml 解析期间出现错误,不知道为什么: ORA-31011:XML 解析失败 ORA-19202:XML 处理 LPX-00229 中发生错误:输入源为空 ORA-06512:在“SYS.XMLTYPE”,第 272 行 ORA-06512:在第 1 行
    • 我也尝试了第一个选择查询,它告诉我:“查询失败,因为当前不支持所有列类型。”我的oracle版本是11g Enterprise Edition Release 11.2.0.4.0
    • @user3172596 - “查询失败”消息听起来像是来自您的客户端(它是什么?),可能是因为它无法处理 XMLType;也许用.getclobval()试试?
    • @user3172596 - 对于更新,您的表中是否有 xmldata 为空或空的行?
    • updatexml 是否独立于不同的 oracle sql 工具?因为SQLTools的intellisense检测不到关键字updatexml
    猜你喜欢
    • 2011-12-30
    • 1970-01-01
    • 2016-10-04
    • 2014-04-16
    • 1970-01-01
    • 1970-01-01
    • 2013-07-23
    • 2021-08-30
    • 1970-01-01
    相关资源
    最近更新 更多