Search code examples
xmlplsqlbulkinsertclobxmltype

Oracle 11g: Reading records in XML from CLOB and table update


I am looking for a solution to get data from an XML string stored into a CLOB Oracle DB column to insert them into 2 different tables: table_1 & table_2.

Here is my XML string:

        <?xml version="1.0" encoding="utf-8"?>
        <FIC>
          <LIS_UAT>
            <UAT>
              <COD_SOC>1000</COD_SOC>
              <COD_ETA>1010</COD_ETA>
              <NUM_UAT>0080000228</NUM_UAT>
              <DATA>
                <COD_DEV_MAR></COD_DEV_MAR>
                <COD_TRS_FAC>9000000026</COD_TRS_FAC>
                <MNT_MAR>525</MNT_MAR>
                <NBR_COL>500</NBR_COL>
                <NBR_MET_LIN>0.25</NBR_MET_LIN>
                <PDS_BRT>138</PDS_BRT>
                <PDS_NET>110</PDS_NET>
                <VAL_SURF>4</VAL_SURF>
                <VOL>1</VOL>
              </DATA>
              <LIS_PRO>
                <PRO>
                  <COD_PRO>110089</COD_PRO>
                  <NBR_COL>500</NBR_COL>
                  <PRX>400</PRX>
                  <QTE>250</QTE>
                  <LIB_PRO_DST>MILK POWDER 28.8% CREAM BAG 25 KG IN BULK</LIB_PRO_DST>
                  <NUM_LOT>LOT1</NUM_LOT>
                  <DAT_DLC>2017-01-22T00:00:00</DAT_DLC>
                  <LIB_PRO>MILK POWDER 28.8% CREAM BAG 25 KG IN BULK</LIB_PRO>
                  <COL_PDS>0.267</COL_PDS>
                  <COL_VOL>0.002</COL_VOL>
                  <PCB>1</PCB>
                  <PDS_BRT>0.267</PDS_BRT>
                  <PDS_NET>0.267</PDS_NET>
                  <VOL>0.002</VOL>
                  <COD_EAN>1000</COD_EAN>
                  <COD_TRS>FOURNISSEUR</COD_TRS>
                </PRO>
                 <PRO>
                  <COD_PRO>110090</COD_PRO>
                  <NBR_COL>50</NBR_COL>
                  <PRX>40</PRX>
                  <QTE>25</QTE>
                  <LIB_PRO_DST>MILK POWDER 40% CREAM BAG 25 KG</LIB_PRO_DST>
                  <NUM_LOT>LOT2</NUM_LOT>
                  <DAT_DLC>2017-02-25T00:00:00</DAT_DLC>
                  <LIB_PRO>MILK POWDER 40% CREAM BAG 25 KG</LIB_PRO>
                  <COL_PDS>0.167</COL_PDS>
                  <COL_VOL>0.001</COL_VOL>
                  <PCB>1</PCB>
                  <PDS_BRT>0.267</PDS_BRT>
                  <PDS_NET>0.267</PDS_NET>
                  <VOL>0.002</VOL>
                  <COD_EAN>1001</COD_EAN>
                  <COD_TRS>SYNUTRA</COD_TRS>
                </PRO>
              </LIS_PRO>
            </UAT>
            <UAT>
              <COD_SOC>1000</COD_SOC>
              <COD_ETA>1010</COD_ETA>
              <NUM_UAT>0080000229</NUM_UAT>
              <DATA>
                <COD_DEV_MAR></COD_DEV_MAR>
                <COD_TRS_FAC>9000000027</COD_TRS_FAC>
                <MNT_MAR>52.5</MNT_MAR>
                <NBR_COL>50</NBR_COL>
                <NBR_MET_LIN>0.025</NBR_MET_LIN>
                <PDS_BRT>13.8</PDS_BRT>
                <PDS_NET>11</PDS_NET>
                <VAL_SURF>0.4</VAL_SURF>
                <VOL>1</VOL>
              </DATA>
              <LIS_PRO>
                <PRO>
                  <COD_PRO>82</COD_PRO>
                  <NBR_COL>5000</NBR_COL>
                  <PRX>4000</PRX>
                  <QTE>2500</QTE>
                  <LIB_PRO_DST>DMU Lait non traité -interface SPX !!S2a</LIB_PRO_DST>
                  <NUM_LOT>LOT3</NUM_LOT>
                  <DAT_DLC>2017-03-15T00:00:00</DAT_DLC>
                  <LIB_PRO>DMU Lait non traité -interface SPX !!S2a</LIB_PRO>
                  <COL_PDS>16.7</COL_PDS>
                  <COL_VOL>1</COL_VOL>
                  <PCB>1</PCB>
                  <PDS_BRT>267</PDS_BRT>
                  <PDS_NET>267</PDS_NET>
                  <VOL>2</VOL>
                  <COD_EAN>1003</COD_EAN>
                  <COD_TRS>0000001001</COD_TRS>
                </PRO>
              </LIS_PRO>
            </UAT>
          </LIS_UAT>
        </FIC>
  • Elements value in nodes will be checked for existence in table_1
  • If yes elements value in nodes will be merged in table_1
  • Elements value in Nodes will be inserted(after suppression) in table_2

=> table_2 references fields (FK) COD_SOC, COD_ETA and NUM_UAT of table_1 (PK)

I did this to output the result but I have got a cartesian product (I did not find the way to join the different XMLTABLES

        ALTER SESSION SET nls_numeric_characters = '. ';

        DECLARE
        BEGIN
           FOR uat_crs
              IN ( SELECT  x1.num_uat as num_uat,x2.nbr_col as nbr_col,x3.cod_pro as cod_pro
                     FROM pro_ficj a,
                          XMLTABLE (
                             '/FIC/LIS_UAT/UAT'
                             PASSING A.DOC_XML
                             COLUMNS COD_SOC VARCHAR2 (5) PATH 'COD_SOC',
                                     COD_ETA VARCHAR2 (5) PATH 'COD_ETA',
                                     NUM_UAT VARCHAR2 (17) PATH 'NUM_UAT') x1,
                                     XMLTABLE (
                                    '/FIC/LIS_UAT/UAT/DATA'
                                    PASSING A.DOC_XML
                                    COLUMNS COD_DEV_MAR VARCHAR2 (3) PATH 'COD_DEV_MAR',
                                            COD_TRS_FAC VARCHAR2 (17) PATH 'COD_TRS_FAC',
                                            MNT_MAR NUMBER (10, 2) PATH 'MNT_MAR',
                                            NBR_COL NUMBER (16) PATH 'NBR_COL',
                                            NBR_MET_LIN NUMBER (16, 3) PATH 'NBR_MET_LIN',
                                            PDS_BRT NUMBER (10, 3) PATH 'PDS_BRT',
                                            PDS_NET NUMBER (10, 3) PATH 'PDS_NET',
                                            VAL_SURF NUMBER (16, 3) PATH 'VAL_SURF',
                                            VOL NUMBER (9, 3) PATH 'VOL') X2
                           ,XMLTABLE ('/FIC/LIS_UAT/UAT/LIS_PRO/PRO'
                                                     PASSING A.DOC_XML
                                                     COLUMNS COD_PRO                  VARCHAR2 (17)PATH 'COD_PRO',
                                                             NBR_COL                  NUMBER (5) PATH 'NBR_COL',
                                                             PRX                      NUMBER (16,7) PATH 'PRX',
                                                             QTE                      NUMBER (16) PATH 'QTE',
                                                             LIB_PRO_DST              VARCHAR2 (50) PATH 'LIB_PRO_DST',
                                                             NUM_LOT                  VARCHAR2 (17) PATH 'NUM_LOT',
                                                             DAT_DLC                  varchar2(50) PATH 'DAT_DLC',
                                                             LIB_PRO                  VARCHAR2 (70) PATH 'LIB_PRO',
                                                             COL_PDS                  NUMBER (10, 3) PATH 'COL_PDS',
                                                             COL_VOL                  NUMBER (11, 4) PATH 'COL_VOL',
                                                             PCB                      NUMBER (4) PATH 'PCB',
                                                             PDS_BRT                  NUMBER (10, 3) PATH 'PDS_BRT',
                                                             PDS_NET                  NUMBER (10,3) PATH 'PDS_NET',
                                                             VOL                      NUMBER (9,3) PATH 'VOL',
                                                             COD_EAN                  VARCHAR2 (17) PATH 'COD_EAN',
                                                             COD_TRS                  VARCHAR2 (17) PATH 'COD_TRS'
                                                            ) X3
                    WHERE a.num_int_jrn = 881)
           LOOP



                DBMS_OUTPUT.PUT_LINE('uatv : ' || uat_crs.num_uat || ' - data : ' || uat_crs.NBR_COL ||' - pro : ' || uat_crs.COD_PRO);

              END LOOP;

        END;
        /

Solution

  • Finally I found a solution:

    ALTER SESSION SET nls_numeric_characters = '. ';
    
    Declare
    
    
    BEGIN
       FOR uat_crs
          IN (     SELECT x1.cod_soc AS COD_SOC,
                          x1.cod_eta AS COD_ETA,
                          x1.num_uat AS NUM_UAT,
                          'U' AS TYP_UAT,
                          X2.*
                     FROM pro_ficj a,
                          XMLTABLE ('/FIC/LIS_UAT/UAT'
                                    PASSING A.DOC_XML
                                    COLUMNS COD_SOC VARCHAR2 (5) PATH 'COD_SOC',
                                            COD_ETA VARCHAR2 (5) PATH 'COD_ETA',
                                            NUM_UAT VARCHAR2 (17) PATH 'NUM_UAT',
                                            DATA XMLTYPE PATH 'DATA') x1,
                          XMLTABLE (
                             '/DATA'
                             PASSING X1.DATA
                             COLUMNS COD_DEV_MAR VARCHAR2 (3) PATH 'COD_DEV_MAR',
                                     COD_TRS_FAC VARCHAR2 (17) PATH 'COD_TRS_FAC',
                                     MNT_MAR NUMBER (10, 2) PATH 'MNT_MAR',
                                     NBR_COL NUMBER (16) PATH 'NBR_COL',
                                     NBR_MET_LIN NUMBER (16, 3) PATH 'NBR_MET_LIN',
                                     PDS_BRT NUMBER (10, 3) PATH 'PDS_BRT',
                                     PDS_NET NUMBER (10, 3) PATH 'PDS_NET',
                                     VAL_SURF NUMBER (16, 3) PATH 'VAL_SURF',
                                     VOL NUMBER (9, 3) PATH 'VOL') x2
                    WHERE num_int_jrn = 881)
       LOOP
          DBMS_OUTPUT.put_line ('UAT : ' || uat_crs.num_uat);
          DBMS_OUTPUT.PUT_LINE (
                'data : '
             || uat_crs.COD_DEV_MAR
             || ' - '
             || uat_crs.COD_TRS_FAC
             || ' - '
             || uat_crs.NBR_COL
             || ' - '
             || uat_crs.NBR_MET_LIN
             || ' - '
             || uat_crs.PDS_BRT
             || ' - '
             || uat_crs.PDS_NET
             || ' - '
             || uat_crs.VAL_SURF
             || ' - '
             || uat_crs.VOL);
    
    
          FOR pro_crs
             IN (     SELECT y1.cod_soc,
                             y1.cod_eta,
                             y1.num_uat,
                             y2.*
                        FROM pro_ficj a,
                             XMLTABLE ('/FIC/LIS_UAT/UAT'
                                       PASSING A.DOC_XML
                                       COLUMNS COD_SOC VARCHAR2 (5) PATH 'COD_SOC',
                                               COD_ETA VARCHAR2 (5) PATH 'COD_ETA',
                                               NUM_UAT VARCHAR2 (17) PATH 'NUM_UAT',
                                               PRODUITS XMLTYPE PATH 'LIS_PRO') y1,
                             XMLTABLE (
                                '/LIS_PRO/PRO'
                                PASSING y1.produits
                                COLUMNS COD_PRO VARCHAR2 (17) PATH 'COD_PRO',
                                        NBR_COL NUMBER (5) PATH 'NBR_COL',
                                        PRX NUMBER (16, 7) PATH 'PRX',
                                        QTE NUMBER (16) PATH 'QTE',
                                        LIB_PRO_DST VARCHAR2 (50) PATH 'LIB_PRO_DST',
                                        NUM_LOT VARCHAR2 (17) PATH 'NUM_LOT',
                                        DAT_DLC VARCHAR2 (50) PATH 'DAT_DLC',
                                        LIB_PRO VARCHAR2 (70) PATH 'LIB_PRO',
                                        COL_PDS NUMBER (10, 3) PATH 'COL_PDS',
                                        COL_VOL NUMBER (11, 4) PATH 'COL_VOL',
                                        PCB NUMBER (4) PATH 'PCB',
                                        PDS_BRT NUMBER (10, 3) PATH 'PDS_BRT',
                                        PDS_NET NUMBER (10, 3) PATH 'PDS_NET',
                                        VOL NUMBER (9, 3) PATH 'VOL',
                                        COD_EAN VARCHAR2 (17) PATH 'COD_EAN',
                                        COD_TRS VARCHAR2 (17) PATH 'COD_TRS') y2
                       WHERE     a.num_int_jrn = 881
                             AND y1.cod_soc = uat_crs.cod_soc
                             AND y1.cod_eta = uat_crs.cod_eta
                             AND y1.num_uat = uat_crs.num_uat)
          LOOP
             DBMS_OUTPUT.put_line ('-> Produit : ' || pro_crs.cod_pro);
    
             DBMS_OUTPUT.PUT_LINE (
                   'pro : '
                || pro_crs.COD_PRO
                || ' - '
                || pro_crs.NBR_COL
                || ' - '
                || pro_crs.PRX
                || ' - '
                || pro_crs.QTE
                || ' - '
                || pro_crs.LIB_PRO_DST
                || ' - '
                || pro_crs.NUM_LOT
                || ' - '
                || pro_crs.DAT_DLC
                || ' - '
                || pro_crs.LIB_PRO
                || ' - '
                || pro_crs.COL_PDS
                || ' - '
                || pro_crs.COL_VOL
                || ' - '
                || pro_crs.PCB
                || ' - '
                || pro_crs.PDS_BRT
                || ' - '
                || pro_crs.PDS_NET
                || ' - '
                || pro_crs.VOL
                || ' - '
                || pro_crs.COD_EAN
                || ' - '
                || pro_crs.COD_TRS);
          END LOOP;
       END LOOP;
    END;
    /
    

    output:

    UAT : 0080000228 data : - 9000000026 - 500 - .25 - 138 - 110 - 4 - 1 -> Produit : 110089 pro : 110089 - 500 - 400 - 250 - MILK POWDER 28.8% CREAM BAG 25 KG IN BULK - LOT1 - 2017-01-22T00:00:00 - MILK POWDER 28.8% CREAM BAG 25 KG IN BULK - .267 - .002 - 1 - .267 - .267 - .002 - 1000 - FOURNISSEUR -> Produit : 110090 pro : 110090 - 50 - 40 - 25 - MILK POWDER 40% CREAM BAG 25 KG - LOT2 - 2017-02-25T00:00:00 - MILK POWDER 40% CREAM BAG 25 KG - .167 - .001 - 1 - .267 - .267 - .002 - 1001 - SYNUTRA UAT : 0080000229 data : - 9000000027 - 50 - .025 - 13.8 - 11 - .4 - 1 -> Produit : 82 pro : 82 - 5000 - 4000 - 2500 - DMU Lait non traité -interface SPX !!S2a - LOT3 - 2017-03-15T00:00:00 - DMU Lait non traité -interface SPX !!S2a - 16.7 - 1 - 1 - 267 - 267 - 2 - 1003 - 0000001001