简体   繁体   English

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

[英]extract value present between XML tags from a blob in Oracle SQL

these data is present in a blob COLUMN ("MSG") in my ADMINTXNUNAUTHDATA table 这些数据存在于我的ADMINTXNUNAUTHDATA表中的Blob COLUMN(“ MSG”)中

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

I want to show "111" present between <billReferenceNumber>111</billReferenceNumber> 我想在<billReferenceNumber>111</billReferenceNumber>之间显示“ 111”

and some other values coming from different tables in a single query 和一些其他值来自单个查询中的不同表

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;

I would not recommend searching for XML tags with INSTR as it is space sensitive, for instance, it wouldn't find <idBiller>111</idBiller > or <idBiller a="x">111</idBiller> . 我不建议使用INSTR搜索XML标签,因为它对空间敏感,例如,找不到<idBiller>111</idBiller ><idBiller a="x">111</idBiller> It is XML after all, which is supposedly easy to parse. 毕竟它是XML,据认为很容易解析。 (Nobody mentioned the awfull syntax, though). (不过,没有人提到awfull语法)。

Secondly, BLOB is totally the wrong datatype. 其次, BLOB完全是错误的数据类型。 It is for binary data. 它用于二进制数据。 Just wait for the first customer called Agüero or Jørgensen. 只需等待名为AgüeroJørgensen的第一个客户 The appropriate datatype for XML in Oracle is XMLTYPE : 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>');

You can then search records by idBiller: 然后可以通过idBiller搜索记录:

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

and extract tag values from the XML: 并从XML中提取标签值:

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

To convert the XML text to a normal datatype, use 要将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

If you cannot change (or let change) the table structure, you could in theory convert the BLOB to XMLTYPE on the fly, but I have no idea about the performance impact: 如果您不能更改(或允许更改)表结构,则理论上可以将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);

For the conversion from BLOB to XMLTYPE , see convert oracle blob to xml type 有关从BLOBXMLTYPE的转换,请参见将oracle blob转换为xml类型。

Xmltype constructor is overridden. Xmltype构造函数被覆盖。 One version is xmltype(blob,csid), blob is blob, csid is character set ID number corresponding to character set name. 一种版本是xmltype(blob,csid),blob是blob,csid是与字符集名称相对应的字符集ID号。 For utf8 it is 871. 对于utf8,它是871。

Check example. 检查示例。 First part is only to prepare blob value. 第一部分只是准备Blob值。 In 2nd part i'm converting blob to xml using csid and i'm extracting data from xml using xmltable. 在第二部分中,我将使用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
       )

; ;

I'm assuming that your xml is encoded with utf8 我假设您的xml是用utf8编码的

You can use SUBSTRING_INDEX to do this: 您可以使用SUBSTRING_INDEX执行此操作:

Sample: 样品:

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)]>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM