【问题标题】:extract value present between XML tags from a blob in Oracle SQL从 Oracle SQL 中的 blob 中提取 XML 标记之间存在的值
【发布时间】:2018-12-14 22:43:16
【问题描述】:

这些数据存在于我的 ADMINTXNUNAUTHDATA 表中的 blob COLUMN ("MSG") 中

<PayBillerRequestDTO><idCustomer>00000024</idCustomer><idBiller>VODA</idBiller><billerName>ojas yadnik </billerName><billReferenceNumber>111</billReferenceNumber></PayBillerRequestDTO>

我想在&lt;billReferenceNumber&gt;111&lt;/billReferenceNumber&gt;之间显示“111”

以及来自单个查询中不同表的其他一些值

select mbl.idbiller as BILLNUMBER,
       mbl.billernickname AS BILLERNICKNAME,
       mts.idchanneluser AS USERNAME,
       adm.NUMAMOUNT AS AMOUNT,
       adm.ACCOUNTNO AS ACCOUNTNUM,
       adm.DATINITIATION AS TRANSACTIONDATE,
       adm.codcurr as CURRENCY
  from mstbiller mbl, ADMINTXNUNAUTHDATA adm, mstchanneluser mts
 where MTS.IDCHANNELUSER = '??'
   and adm.idinitiator = mts.iduser 
   and adm.txnid = 'BPA'
   and mbl.idbiller ='?'
   AND dbms_lob.instr(MSG, utl_raw.CAST_TO_RAW('<idBiller>?</idBiller>'), 1, 1) > 0;

【问题讨论】:

  • 请帮助我们编辑您的问题,使其更易于理解。连接表和所有其他列与您的问题无关。但是对于带有msg 的表,我们希望看到创建语句或至少是列的数据类型。请同时编辑标签。这对我来说看起来像 Oracle 语法,还是 mysql 也有一个 utl_raw 包?
  • 您使用的是 MySQL 还是 Oracle?
  • 今日提示:切换到现代、明确的JOIN 语法。更容易编写(没有错误),更容易阅读(和维护),并且在需要时更容易转换为外连接。
  • 您确定数据类型是BLOB 而不是CLOB? XML 是字符数据...
  • 您可能会在该问题上找到答案:stackoverflow.com/questions/51195105/…

标签: sql oracle oracle11g blob


【解决方案1】:

Xmltype 构造函数被覆盖。一个版本是 xmltype(blob,csid), 斑点是斑点, csid 是字符集名称对应的字符集 ID 号。对于 utf8,它是 871。

检查示例。第一部分只是准备 blob 值。在第二部分中,我使用 csid 将 blob 转换为 xml,并使用 xmltable 从 xml 中提取数据。

    create table blob_xml (a blob);

    declare 
      cisd number;
      myblob blob;
    begin 
-- save xml as blob
        SELECT NLS_CHARSET_ID('UTF8') into cisd FROM DUAL; 
        myblob := xmltype('<PayBillerRequestDTO><idCustomer>00000024</idCustomer><idBiller>VODA</idBiller><billerName>ojas yadnik </billerName><billReferenceNumber>111</billReferenceNumber></PayBillerRequestDTO>').getblobVal(cisd); 
       insert into blob_xml values(myblob);
       commit;
    end; 


        select * from blob_xml,xmltable('PayBillerRequestDTO' passing xmltype(a,871)
      columns idCustomer varchar2(4000) path 'idCustomer'
      ,idBiller varchar2(4000) path 'idBiller'
      ,billerName  varchar2(4000) path 'billerName'
      ,billReferenceNumber varchar2(4000) path 'billReferenceNumber'
      --etc
       )

;

我假设你的 xml 是用 utf8 编码的

【讨论】:

    【解决方案2】:

    我不建议使用 INSTR 搜索 XML 标记,因为它对空间敏感,例如,它不会找到 &lt;idBiller&gt;111&lt;/idBiller &gt;&lt;idBiller a="x"&gt;111&lt;/idBiller&gt;。毕竟是 XML,据说很容易解析。 (不过没有人提到糟糕的语法)。

    其次,BLOB 是完全错误的数据类型。它用于二进制数据。只需等待名为 AgüeroJørgensen 的第一个客户。 Oracle 中 XML 的适当数据类型是 XMLTYPE

    CREATE TABLE admintxnunauthdata (
      accountno NUMBER,
      msg XMLTYPE
    ) XMLTYPE COLUMN msg STORE AS SECUREFILE BINARY XML (COMPRESS HIGH);
    
    INSERT INTO admintxnunauthdata (accountno, msg) VALUES (1,
     '<PayBillerRequestDTO><idCustomer>00000024</idCustomer><idBiller>VODA</idBiller><billerName>ojas yadnik </billerName><billReferenceNumber>111</billReferenceNumber></PayBillerRequestDTO>');
    INSERT INTO admintxnunauthdata (accountno, msg) VALUES (2,
     '<PayBillerRequestDTO><idCustomer>00000025</idCustomer><idBiller>JODA</idBiller><billerName>ojas yadnik </billerName><billReferenceNumber>222</billReferenceNumber></PayBillerRequestDTO>');
    

    然后您可以按 idBiller 搜索记录:

    SELECT * 
      FROM admintxnunauthdata
     WHERE XMLExists('/PayBillerRequestDTO[idBiller="VODA"]' PASSING msg);
    

    并从 XML 中提取标签值:

    SELECT accountno,
           XMLQuery('/PayBillerRequestDTO/billReferenceNumber/text()' 
             PASSING msg RETURNING CONTENT)
      FROM admintxnunauthdata
     WHERE XMLExists('/PayBillerRequestDTO[idBiller="VODA"]' PASSING msg);
    

    要将 XML 文本转换为普通数据类型,请使用

    SELECT accountno,
           XMLCast(XMLQuery('/PayBillerRequestDTO/billReferenceNumber/text()' 
             PASSING msg RETURNING CONTENT) AS NUMBER) AS billreferencenumber
      FROM admintxnunauthdata
     WHERE XMLExists('/PayBillerRequestDTO[idBiller="VODA"]' PASSING msg);
    
    ACCOUNTNO BILLREFERENCENUMBER
            1                 111
    

    如果您不能更改(或让更改)表结构,理论上您可以即时将 BLOB 转换为 XMLTYPE,但我不知道性能影响:

    SELECT accountno,
           XMLCast(XMLQuery('/PayBillerRequestDTO/billReferenceNumber/text()' 
             PASSING msg RETURNING CONTENT) AS NUMBER) AS billreferencenumber
      FROM (
            SELECT accountno, XMLTYPE(msg,1) as msg 
              FROM admintxnunauthdata
           )
     WHERE XMLExists('/PayBillerRequestDTO[idBiller="VODA"]' PASSING msg);
    

    关于从BLOBXMLTYPE 的转换,请参见convert oracle blob to xml type

    【讨论】:

      【解决方案3】:

      您可以使用 SUBSTRING_INDEX 来执行此操作:

      示例:

      MariaDB [(none)]> SET @x:="<PayBillerRequestDTO><idCustomer>00000024</idCustomer><idBiller>VODA</idBiller><billerName>ojas yadnik </billerName><billReferenceNumber>111</billReferenceNumber></PayBillerRequestDTO>";
      Query OK, 0 rows affected (0.00 sec)
      
      MariaDB [(none)]> SELECT SUBSTRING_INDEX( SUBSTRING_INDEX( @x, "<billReferenceNumber>", -1), '</billReferenceNumber>', 1) as result;
      +--------+
      | result |
      +--------+
      | 111    |
      +--------+
      1 row in set (0.00 sec)
      
      MariaDB [(none)]>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-24
        • 1970-01-01
        • 2022-01-27
        • 1970-01-01
        相关资源
        最近更新 更多