【问题标题】:How can I extract the first node value from a XMLTYPE?如何从 XMLTYPE 中提取第一个节点值?
【发布时间】:2022-10-06 19:53:35
【问题描述】:

我有一个 xml,它在我的表的 clob 字段中

这是我目前使用的代码:

create table
   xml_key
(  
   mycol number,
   xml   clob
);


insert into xml_key
values(1653,
\'<AppHdr>
    <Fr>
      <FIId>
        <FinInstnId>
          <BICFI>CRESUS33</BICFI>
        </FinInstnId>
      </FIId>
    </Fr>
    <To>
      <FIId>
        <FinInstnId>
          <BICFI>CAYTTRISXXX</BICFI>
        </FinInstnId>
      </FIId>
    </To>
    <BizMsgIdr>e9aab4a5-bc32-4548-93f6-aa47dd97d77</BizMsgIdr>
    <MsgDefIdr>pac.004.001.09</MsgDefIdr>
    <BizSvc>swift.cbprplus.02</BizSvc>
    <CreDt>2019-08-12T13:59:26+01:00</CreDt>
    <Rltd>
      <Fr>
        <FIId>
          <FinInstnId>
            <BICFI>LOYDGB21002</BICFI>
          </FinInstnId>
        </FIId>
      </Fr>
      <To>
        <FIId>
          <FinInstnId>
            <BICFI>CRESUS33</BICFI>
          </FinInstnId>
        </FIId>
      </To>
      <BizMsgIdr>1234567890</BizMsgIdr>
        <MsgDefIdr>pacs.008.001.08</MsgDefIdr>
            <CreDt>2019-08-12T12:59:26+01:00</CreDt>
        </Rltd>
    </AppHdr>\');

当我从 xml 中提取 BIC 代码时,我遇到了问题。 我不想要像 CRESUS33LOYDGB21002 这样的双节点 如何从 xml 中仅提取 CRESUS33 作为 FromBIC?

 select XMLTYPE(t.xml).EXTRACT(\'//Fr/FIId/FinInstnId/BICFI/text()\').getStringVal()  fromBIC,
     XMLTYPE(t.xml).EXTRACT(\'//Rltd/Fr/FIId/FinInstnId/BICFI/text()\').getStringVal()  RltdFromBIC
          from xml_key t
         where mycol=1653 ;
    
    FROMBIC                           RLTDFROMBIC
    --------------------------------- --------------------------------------
    CRESUS33LOYDGB21002               LOYDGB21002

谢谢

    标签: sql oracle extract xmltype


    【解决方案1】:

    问题是您在两个提取调用中都使用//Fr 作为快捷方式,并且Fr 是直接在AppHdrAppHdr/Rltd 下的节点,第一个XPath 匹配这两者,你最终得到两者结合的值。第二个 Xpath 更具选择性,因此只能看到第二个。

    如果您为两者提供完整路径,那么您将不会遇到该问题:

     select XMLTYPE(t.xml).EXTRACT('/AppHdr/Fr/FIId/FinInstnId/BICFI/text()').getStringVal()  fromBIC,
         XMLTYPE(t.xml).EXTRACT('/AppHdr/Rltd/Fr/FIId/FinInstnId/BICFI/text()').getStringVal()  RltdFromBIC
              from xml_key t
             where mycol=1653 ;
    

    您还可以使用 XMLQuery:

    select
      XMLQuery('/AppHdr/Fr/FIId/FinInstnId/BICFI/text()'
        passing XMLTYPE(t.xml)
        returning content).getStringVal() as fromBIC,
      XMLQuery('/AppHdr/Rltd/Fr/FIId/FinInstnId/BICFI/text()'
        passing XMLTYPE(t.xml)
        returning content).getStringVal() as RltdFromBIC
    from xml_key t
    where mycol=1653;
    

    或 XML 表:

    select x.fromBIC, x.RltdFromBIC
    from xml_key t
    cross apply XMLTable(
      '/AppHdr'
      passing XMLTYPE(t.xml)
      columns
        fromBIC path 'Fr/FIId/FinInstnId/BICFI',
        RltdFromBIC path 'Rltd/Fr/FIId/FinInstnId/BICFI'
    ) x
    where mycol=1653;
    
    FROMBIC RLTDFROMBIC
    CRESUS33 LOYDGB21002

    三人皆归

    db<>fiddle


    如果您仍在使用 12c 之前的版本,那么您可以使用 cross join 而不是 cross apply

    select x.fromBIC, x.RltdFromBIC
    from xml_key t
    cross join XMLTable(
      '/AppHdr'
      passing XMLTYPE(t.xml)
      columns
        fromBIC path 'Fr/FIId/FinInstnId/BICFI',
        RltdFromBIC path 'Rltd/Fr/FIId/FinInstnId/BICFI'
    ) x
    where mycol=1653;
    

    他们aren't exactly the same 但在这里不应该有所作为。

    db<>fiddle

    【讨论】:

    • 这是非常好的解决方案。我投了赞成票,但第三个选项不起作用。 SELECT 查询有问题
    • @SachinPadha - 你可以看到它在 db<>fiddle 中工作。但是,如果您使用的是 12.1 之前的版本(我认为),它不会理解“应用”并会抛出“ORA-00905:缺少关键字” - 但您可以将 cross apply 更改为 cross join
    • 哦好。知道了。 “交叉加入”正在工作
    【解决方案2】:

    如果de标签之间没有区别并且有这样的重复复杂类型,我有一个新问题

       <pacs:CdtTrfTxInf>
          <pacs:PmtId>
            <pacs:InstrId>N2200000000316</pacs:InstrId>
            <pacs:EndToEndId>ISO TESTING BOS</pacs:EndToEndId>
            <pacs:TxId>N2200000000316</pacs:TxId>
            <pacs:UETR>4e6a8670-e17b-4adb-a567-b20cd155e842</pacs:UETR>
          </pacs:PmtId>
          <pacs:IntrBkSttlmAmt Ccy="AUD">100.00</pacs:IntrBkSttlmAmt>
          <pacs:IntrBkSttlmDt>2022-10-05</pacs:IntrBkSttlmDt>
          <pacs:InstdAmt Ccy="AUD">120.00</pacs:InstdAmt>
          <pacs:ChrgBr>SHAR</pacs:ChrgBr>
          <pacs:ChrgsInf>
            <pacs:Amt Ccy="AUD">0.00</pacs:Amt>
            <pacs:Agt>
              <pacs:FinInstnId>
                <pacs:BICFI>LIKIAU2SXXX</pacs:BICFI>
              </pacs:FinInstnId>
            </pacs:Agt>
          </pacs:ChrgsInf>
          <pacs:ChrgsInf>
            <pacs:Amt Ccy="AUD">020.00</pacs:Amt>
            <pacs:Agt>
              <pacs:FinInstnId>
                <pacs:BICFI>LIKIAU2SXXX</pacs:BICFI>
              </pacs:FinInstnId>
            </pacs:Agt>
          </pacs:ChrgsInf>
    

    当我选择时在这里

     select XMLTYPE(t.xml).EXTRACT('//FIToFICstmrCdtTrf/CdtTrfTxInf/ChrgsInf/Amt/@Ccy').getStringVal()  Currency,
         XMLTYPE(t.xml).EXTRACT('//FIToFICstmrCdtTrf/CdtTrfTxInf/ChrgsInf/Amt/text()').getStringVal()  amount
              from xml_key t
    

    货币金额


    澳元 0.00020.00

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-22
      • 2010-10-11
      • 2020-02-08
      • 2013-07-06
      • 1970-01-01
      • 2011-09-07
      • 2019-12-20
      • 2019-08-19
      相关资源
      最近更新 更多