如何在 Oracle SQL 中搜索特定的 XML 值?

Posted

技术标签:

【中文标题】如何在 Oracle SQL 中搜索特定的 XML 值?【英文标题】:How do I search for a specific XML value in Oracle SQL? 【发布时间】: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';

有什么想法吗?

【问题讨论】:

【参考方案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 我不知道,你还没有分享你的查询或数据。

以上是关于如何在 Oracle SQL 中搜索特定的 XML 值?的主要内容,如果未能解决你的问题,请参考以下文章

在 gmail api 中搜索特定的 in-reply-to 标头

在 htop 中搜索特定的进程名称

在一个用 JSON 填充的 NSArray 中搜索特定的标题

Javascript,Nodejs:在文件中搜索特定的单词字符串

如何在值列中搜索特定值并在 Big Query SQL 中替换为该特定值?

在所有表中的所有字段中搜索特定值 (Oracle)