【问题标题】:How to search for a string in a CLOB and display the value after it in Oracle SQL?如何在 CLOB 中搜索字符串并在 Oracle SQL 中显示其后的值?
【发布时间】:2020-12-15 16:04:53
【问题描述】:

我需要在一个查询中执行此操作,我不确定是否可能。我有一个名为 STORE_VALUES 的表,其中包含 CODE 和 VALUE 列。 CODE 是这个表的 PKEY。 VALUE 是一个包含大型 XML 对象的 CLOB 列

CODE VALUE
DataSet1 ....some xml... <Version>1</Version>...some more xml
DataSet2 ....some xml... <Version>5</Version>...some more xml

我需要寻找标签 的第一个实例并显示它后面的数字(有多个实例,但我只关心第一个) 我相信我需要使用 dbms_lob.instr 但我不知道该怎么做。任何帮助表示赞赏,谢谢!

这是我迄今为止尝试过的,但它只显示了我需要的值之后的任何内容(因此它显示 ,然后是 clob 的其余部分)

从 STORE_VALUES 中选择代码,dbms_lob.substr(VALUE, dbms_lob.instr(VALUE,''),dbms_lob.INSTR(VALUE,''));

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    使用您提供的有限信息,我创建了一个包含一些示例数据的示例表。您必须记住的一个警告是您必须遍历 xml。由于我在 CLOB 列中只有“版本”,因此我只需要在下面的查询中使用 Version。但是,如果它有一个父元素,例如 Versions,那么我将不得不调整我的查询以执行类似 '/Versions/Version' 的操作,以便在 xml 中获取该元素。

        --table ddl  
        CREATE TABLE STORE_VALUES
       (    CODE VARCHAR2(20), 
            VALUE CLOB
       ) ;
    
         -- potential insert statement. --
         INSERT INTO STORE_VALUES (CODE, VALUE) VALUES ('1', '<Version>1</Version>');
         INSERT INTO STORE_VALUES (CODE, VALUE) VALUES ('2', '<Version>5</Version>');
    
     --possible query dependent on full xml
    
    SELECT
        extractvalue(
            xmltype(
                dbms_lob.substr(
                    value, 3000
                )
            ), 'Version'
        ) version_el
    FROM
        store_values;
    

    【讨论】:

    • 我只希望得到版本标签后面的数字。在上面的示例中,我希望显示 1 和 5。
    • 谢谢,但我正在处理许多不同类型的 XML 对象。因此,版本标签将位于不同的父元素下。我希望能够使用简单的字符串函数来做到这一点,我只查找“”的第一次出现并显示它之后的值,因为这适用于所有情况。
    • VALUE 列似乎不是真正的 xml,因为它之前和之后都有一些字符串,因此 XML 解析似乎不起作用。
    【解决方案2】:

    由于您的 VALUE 列是 XML,您可以尝试使用可用的 XML 函数来提取值。从 XML 中提取“版本”的实际 XPath 可能因 XML 文档的结构而异。

    查询

    WITH
        store_values (code, VALUE)
        AS
            (SELECT 'DataSet1',
                    TO_CLOB ('<doc><attr1>abc</attr1><Version>1</Version><attr2>def</attr2></doc>')
               FROM DUAL
             UNION ALL
             SELECT 'DataSet2',
                    TO_CLOB ('<doc><attr1>ghi</attr1><Version>5</Version><attr2>jkl</attr2></doc>')
               FROM DUAL)
    SELECT code, EXTRACTVALUE (xmltype (VALUE), '/doc/Version/text()') AS version_no
      FROM store_values;
    

    结果

           CODE    VERSION_NO
    ___________ _____________
    DataSet1    1
    DataSet2    5
    

    更新

    由于VALUE 列不包含真正的 XML,您可以使用 REGEX 表达式提取值。下面的查询将给出与上面相同的结果。

    WITH
        store_values (code, VALUE)
        AS
            (SELECT 'DataSet1',
                    TO_CLOB ('<doc><attr1>abc</attr1><Version>1</Version><attr2>def</attr2></doc>')
               FROM DUAL
             UNION ALL
             SELECT 'DataSet2',
                    TO_CLOB ('<doc><attr1>ghi</attr1><Version>5</Version><attr2>jkl</attr2></doc>')
               FROM DUAL)
    SELECT code,
           REGEXP_REPLACE (REGEXP_SUBSTR (VALUE, '<Version>.*</Version>'), '<[^>]*>')     AS version_no
      FROM store_values;
    

    【讨论】:

    • 如果只有 OP 没有明确说明 XML 相当大。在这种情况下,CLOB 的唯一 XML 解析将消耗大量时间。除此之外,你的答案是完美的。
    • XML 解析似乎不起作用,因为该列似乎不是真正的 XML,所以我不得不求助于查找子字符串来查找
    猜你喜欢
    • 2013-07-13
    • 1970-01-01
    • 2018-12-06
    • 1970-01-01
    • 1970-01-01
    • 2013-06-08
    • 2014-05-10
    • 2021-06-21
    • 1970-01-01
    相关资源
    最近更新 更多