【问题标题】:How do I search for a specific XML value in Oracle SQL?如何在 Oracle SQL 中搜索特定的 XML 值?
【发布时间】:2021-11-14 02:50:57
【问题描述】:

我正在尝试在 SQL 表 (BLOB) 的 XML 二进制类型列中搜索给定值。

该表有 +3000 条记录。我需要从如下所示的 XML 中查找与 /properties/ip/ 中特定 IP 对应的所有值:

<?xml version="1.0" encoding="UTF-8"?>
<properties>
   <port>8000</port>
   <ip>12.345.67.80</ip>
</properties>

到目前为止,我已经能够获得 一些 输出,但不是我需要的(我只能使用最后一个 WHERE 子句运行查询,而不是没有):

SELECT
    d.*,
    extractvalue(xmltype(d.CONFIGURATION,nls_charset_id('AL32UTF8')),'properties/ip') as ip_lookup
FROM
    AZ.DEVICES d
WHERE
    NAME = 'Door-Entrance';

我对查找具有特定 IP 的所有记录很感兴趣,所以是这样的:

SELECT
    d.*,
    extractvalue(xmltype(d.CONFIGURATION,nls_charset_id('AL32UTF8')),'properties/ip') as ip_lookup
FROM
    AZ.DEVICES d
WHERE
    ip_lookup = '12.345.67.80';

有什么想法吗?

【问题讨论】:

    标签: sql xml oracle blob


    【解决方案1】:

    您可以使用 Oracle 推荐的 XMLTABLE 而不是已弃用的 函数XMLSEQUENCEEXTRACTVALUE

    WITH devices(configuration,name) AS
     (SELECT XMLType('<?xml version="1.0" encoding="UTF-8"?>
            <properties>
               <port>8000</port>
               <ip>12.345.67.80</ip>
            </properties>'),
             'Door-Entrance'
        FROM dual)
    SELECT ip
      FROM devices,
           XMLTABLE('/properties' PASSING devices.configuration COLUMNS "IP"
                    VARCHAR2(50) PATH 'ip')
     WHERE name = 'Door-Entrance'
    

    Demo

    【讨论】:

    • 嗨,巴巴罗斯,感谢您的评论!最后我是否可以制作类似“WHERE ip_lookup = '12.345.67.80'”的内容来搜索特定的IP?
    • 不客气@jfe1337。对于前一个已弃用的情况,您仍然可以使用this 作为一种向后兼容的选项。对于您当前的语句,由于 XmlType 的使用方式,应该会引发错误。
    • 我有一个大表,其中包含 BLOB 列中的 XML 类型值。我能用 WITH 子句解析所有这些,找到一个特定的 IP 吗?据我所知,根据您的查询,这只是 1 条 XML 记录。谢谢!
    • 正如已经提到的 extractvalue 已被弃用并且不应该被首选 @jfe1337 ,以 WITH 子句开头的查询只是一个说明,您可以创建一个带有 XmlType 列的表(即configuration) ,这将检查值的正确性(XML 值是否存在违规),如在此 demo 而不是 BLOB 中。
    • 再次感谢您的友好回复,Barbaros,我现在明白您的意思了。我正在使用已配置为 BLOB 的数据库。我可以以某种方式为此 DEVICES 表中的每条记录选择 每个 IP 吗?我想将它们全部提取出来以便能够识别重复项。
    【解决方案2】:

    您可以使用XMLTABLEWHERE 子句中的任一过滤器:

    SELECT *
    FROM   AZ.devices d
           CROSS APPLY XMLTABLE(
             '/properties'
             PASSING XMLTYPE(d.configuration,nls_charset_id('UTF8'))
             COLUMNS
               port NUMBER(5,0)  PATH './port',
               ip   VARCHAR2(15) PATH './ip'
           ) x
    WHERE  x.ip = '12.345.67.80';
    

    或者在 XPath 中:

    SELECT *
    FROM   AZ.devices d
           CROSS APPLY XMLTABLE(
             '/properties[ip="12.345.67.80"]'
             PASSING XMLTYPE(d.configuration,nls_charset_id('UTF8'))
             COLUMNS
               port NUMBER(5,0)  PATH './port',
               ip   VARCHAR2(15) PATH './ip'
           ) x
    

    其中,对于样本数据:

    CREATE TABLE AZ.devices (
      name          VARCHAR2(30),
      configuration BLOB
    );
    
    INSERT INTO AZ.devices (name, configuration)
    VALUES (
      'Door-Entrance',
      UTL_RAW.CAST_TO_RAW('<?xml version="1.0" encoding="UTF-8"?>
    <properties>
       <port>8000</port>
       <ip>12.345.67.80</ip>
    </properties>')
    );
    

    两个输出:

    NAME CONFIGURATION PORT IP_LOOKUP
    Door-Entrance <?xml version="1.0" encoding="UTF-8"?>
    <properties>
       <port>8000</port>
       <ip>12.345.67.80</ip>
    </properties>
    8000 12.345.67.80

    db小提琴here

    【讨论】:

    • 您好 MT0,感谢您的友好回复。我认为这是一个很好的方法。但是,我在 CONFIGURATION blob 中确实有很多额外的值,我没有包含在问题中。
    • @jfe1337 然后将它们添加到COLUMNS 子句中,如果你想输出它们,或者如果你不想输出它们就不要。我没有看到问题是什么。
    • @jfe1337 您没有提供任何信息让我回答您关于如何映射它们的问题。我建议您只需在 XMLTABLECOLUMNS 子句中添加适当的行,并使用适当的 Xpath 来映射您要映射的属性,但除此之外我不能更具体,因为您没有分享任何细节。
    • 如果我收到错误“ORA-06502: PL/SQL: numeric or value error ORA-06512: at "SYS.XMLTYPE", line 283”,这是否是由于数据类型映射不正确?
    • @jfe1337 我不知道,你还没有分享你的查询或数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-16
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 2021-12-02
    • 2019-05-07
    • 1970-01-01
    相关资源
    最近更新 更多