从Oracle SQL中的Blob提取XML标记之间存在的值

时间:2018-07-06 10:31:03

标签: sql oracle oracle11g blob

这些数据存在于我的ADMINTXNUNAUTHDATA表中的Blob列(“ MSG”)中

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

我想显示<billReferenceNumber>111</billReferenceNumber>之间的“ 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;

3 个答案:

答案 0 :(得分:0)

我不建议使用INSTR搜索XML标签,因为它对空间敏感,例如,找不到<idBiller>111</idBiller ><idBiller a="x">111</idBiller>。毕竟它是XML,据认为很容易解析。 (不过,没有人提到awfull语法)。

第二,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

答案 1 :(得分:0)

Xmltype构造函数被覆盖。一个版本是xmltype(blob,csid), blob是blob, 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 :(得分:-1)

您可以使用 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)]>