oracle11g解码JSON blob

oracle11g解码JSON blob,json,oracle,oracle11g,Json,Oracle,Oracle11g,我很难将从ORDS接收到的JSON负载解码成blob,所以我决定编写自己的函数。我的表格如下: CREATE TABLE EDI_TRANSIT_UPDATE ( SEQ_NO NUMBER, CREATED_DATE DATE, CREATED_BY VARCHAR2(20 BYTE), LAST_UPDATE_DATE DATE, LAST_UPDATE_BY VARCHAR2(20 BYTE), PROCESSE

我很难将从ORDS接收到的JSON负载解码成blob,所以我决定编写自己的函数。我的表格如下:

CREATE TABLE EDI_TRANSIT_UPDATE
(
  SEQ_NO            NUMBER,
  CREATED_DATE      DATE,
  CREATED_BY        VARCHAR2(20 BYTE),
  LAST_UPDATE_DATE  DATE,
  LAST_UPDATE_BY    VARCHAR2(20 BYTE),
  PROCESSED         VARCHAR2(1 BYTE)            DEFAULT 'N',
  CLOB              BLOB
);
{        "TRAIN_NO": "B1Z1002153250819",
        "CONSIGNMENT_NUMBER": "8094777054",
        "TRAIN_ORIGIN_NAME": "BELLVILLE",
        "TRAIN_ORIGIN_DATE": "2019-08-25T00:00:00",
        "CurrentStationTime": "2019-08-25T22:55:19",
        "CurrentStationPlannedTime": "2019-08-25T20:52:00",
        "TrainLONG": 19.66555008,
        "TrainLAT": -33.4827,
        "CurrentStationDelay": 123,
        "TrainETD": "2019-08-25T15:30:00",
        "TrainETA": "2019-08-26T04:40:00",
        "TrainNewETA": "2019-08-26T06:43:00"
    }
然后我创建了一个JSON解码函数来返回字段的值

CREATE OR REPLACE FUNCTION GET_JSON_FIELD (field varchar2, blob_in IN BLOB,vfield_no number, num_var  varchar2,num_numerics number)
RETURN VARCHAR2 AS
    s             number;
    e             number;
    len           number;
    field_len     number;
    w_ret_field   varchar2(100);
 /* 
    field --> the JSON field that you looking for 
    blob_in the blob containing the JSON payload
    vfield_no is the numeric number or order of the field
    num_var is c or n  (c for character and n for numeric
    num_numerics is for the number of numeric fields before the character field you looking for

   */ 
BEGIN
if num_var='c' then  -- character fields   i.e. fields surrounded with "
  field_len:=length(field)+3;
  select instr( UTL_RAW.CAST_TO_VARCHAR2( blob_in ),field,1,1)+field_len into s from dual;  -- start position
  select instr( UTL_RAW.CAST_TO_VARCHAR2( blob_in ),'",',1,vfield_no-num_numerics) into e from dual;   -- end position

  if e = 0 then   --this if is for the last field
    select instr( UTL_RAW.CAST_TO_VARCHAR2( blob_in ),'"}',1,1) into e from dual;   -- end position
  end if;

  len:=e-s;  -- length of the field
  select UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(blob_in, len,s)) into w_ret_field from dual;  -- the varchar selected

end if;

if num_var='n' then -- numeric fields   i.e. fields not surrounded with "
  field_len:=length(field)+2;
  select instr( UTL_RAW.CAST_TO_VARCHAR2( blob_in ),field,1,1)+field_len into s from dual;  -- start position
  select instr( UTL_RAW.CAST_TO_VARCHAR2( blob_in ),',',1,vfield_no) into e from dual;   -- end position

   if e = 0 then   --this if is for the last field
    select instr( UTL_RAW.CAST_TO_VARCHAR2( blob_in ),',}',1,1) into e from dual;   -- end position
  end if;

  len:=e-s;  -- length of the field

  select UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(blob_in, len,s)) into w_ret_field from dual;  -- the varchar selected

end if;

  RETURN w_ret_field;
END GET_JSON_FIELD;
/
然后我通过传入字段名来调用它,如果它返回一个字符或数字,则是字段的编号,如果它是字符字段,则是它前面的数字字段的编号:

CREATE OR REPLACE PROCEDURE process_transit_data1 IS
w_TRAIN_NO                    VARCHAR2(100);       
w_CONSIGNMENT_NUMBER          VARCHAR2(100);
w_TRAIN_ORIGIN_NAME           VARCHAR2(100);
w_TRAIN_ORIGIN_DATE           VARCHAR2(100);
w_CURRENTSTATIONTIME          VARCHAR2(100);     
w_CURRENTSTATIONPLANNEDTIME   VARCHAR2(100);
w_TRAINLONG                   VARCHAR2(100);        
w_TRAINLAT                    VARCHAR2(100);               
w_CURRENTSTATIONDELAY         VARCHAR2(100);  
w_TRAINETD                    VARCHAR2(100);                  
w_TRAINETA                    VARCHAR2(100);                  
w_TRAINNEWETA                 VARCHAR2(100);

s                             number;
e                             number;
len                           number;
loopcount                     number;
vfield                     number;
nfield                     number;
v_blob    blob;

CURSOR ords
   IS
      SELECT seq_no from EDI_TRANSIT_UPDATE where processed = 'N' order by created_date;


BEGIN

 for processloop in ords loop 

    SELECT clob into v_blob from EDI_TRANSIT_UPDATE where seq_no=processloop.seq_no;   
    trace('TRANSIT','seq_no to process: '||processloop.seq_no);

    vfield:=1;
    nfield:= 1;

   BEGIN  
     w_TRAIN_NO                  :=GET_JSON_FIELD('TRAIN_NO', v_blob, vfield,'c',0 ); -- 'c' is character, 0 is 0 numerics fields before
     vfield:=vfield+1;
   EXCEPTION
     WHEN OTHERS THEN 
       w_TRAIN_NO :=NULL;
   END;

   BEGIN                                        
     w_CONSIGNMENT_NUMBER        :=GET_JSON_FIELD('CONSIGNMENT_NUMBER', v_blob, vfield,'c',0 );
     vfield:=vfield+1;
   EXCEPTION
     WHEN OTHERS THEN 
       w_CONSIGNMENT_NUMBER :=NULL;
   END; 
   BEGIN
     w_TRAIN_ORIGIN_NAME         :=GET_JSON_FIELD('TRAIN_ORIGIN_NAME', v_blob, vfield,'c',0 );
     vfield:=vfield+1;
   EXCEPTION
     WHEN OTHERS THEN 
       w_TRAIN_ORIGIN_NAME :=NULL;
   END;   

   BEGIN 
     w_TRAIN_ORIGIN_DATE         :=GET_JSON_FIELD('TRAIN_ORIGIN_DATE', v_blob, vfield,'c',0 );
     vfield:=vfield+1;
   EXCEPTION
     WHEN OTHERS THEN 
       w_TRAIN_ORIGIN_DATE :=NULL;
   END;   

   BEGIN
     w_CURRENTSTATIONTIME        :=GET_JSON_FIELD('CurrentStationTime', v_blob, vfield,'c',0 ); 
     vfield:=vfield+1;   
    EXCEPTION
     WHEN OTHERS THEN 
       w_CURRENTSTATIONTIME :=NULL;
   END; 

   BEGIN
     w_CURRENTSTATIONPLANNEDTIME :=GET_JSON_FIELD('CurrentStationPlannedTime', v_blob, vfield,'c',0 );
     vfield:=vfield+1;
   EXCEPTION
     WHEN OTHERS THEN 
       w_CURRENTSTATIONPLANNEDTIME :=NULL;
   END; 

   BEGIN
     w_TRAINLONG                 :=GET_JSON_FIELD('TrainLONG', v_blob, vfield,'n',0 );
     vfield:=vfield+1;
   EXCEPTION
     WHEN OTHERS THEN 
       w_TRAINLONG :=NULL;
   END;   

   BEGIN      
     w_TRAINLAT                  :=GET_JSON_FIELD('TrainLAT', v_blob, vfield,'n',0 );  
     vfield:=vfield+1;
   EXCEPTION
     WHEN OTHERS THEN 
       w_TRAINLAT :=NULL;
   END;    

   BEGIN            
     w_CURRENTSTATIONDELAY       :=GET_JSON_FIELD('CurrentStationDelay', v_blob, vfield,'n',0 ); -- 'n' is for a numeric field i.e no " "
     vfield:=vfield+1; 
   EXCEPTION
     WHEN OTHERS THEN 
       w_CURRENTSTATIONDELAY :=NULL;
   END;    

   BEGIN
     w_TRAINETD                  :=GET_JSON_FIELD('TrainETD', v_blob, vfield,'c',3 );     -- 3 for 3 numeric fields before i.e ended with ' not ", 
     vfield:=vfield+1;  
   EXCEPTION
     WHEN OTHERS THEN 
       w_TRAINETD :=NULL;
   END;  

   BEGIN              
    w_TRAINETA                  :=GET_JSON_FIELD('TrainETA', v_blob, vfield,'c',3 );   
    vfield:=vfield+1; 
   EXCEPTION
     WHEN OTHERS THEN 
       w_TRAINETA :=NULL;
   END; 

   BEGIN              
     w_TRAINNEWETA               :=GET_JSON_FIELD('TrainNewETA', v_blob, vfield,'c',3 );
     vfield:=vfield+1;
   EXCEPTION
     WHEN OTHERS THEN 
       w_TRAINNEWETA :=NULL;
   END;


       --insert
       trace('TRANSIT','begin insert'); 

       insert into EDI_TRANSIT_DATA (EDI_TRANSIT_UPDATE_SEQ,TRAIN_NO,CONSIGNMENT_NUMBER,TRAIN_ORIGIN_NAME,TRAIN_ORIGIN_DATE,CURRENTSTATIONTIME,CURRENTSTATIONPLANNEDTIME,TrainLONG,TrainLAT,CURRENTSTATIONDELAY,TRAINETD,TRAINETA,TRAINNEWETA ) 
                  values (processloop.seq_no,w_TRAIN_NO,w_CONSIGNMENT_NUMBER,w_TRAIN_ORIGIN_NAME,REPLACE(w_TRAIN_ORIGIN_DATE,'T',' '),REPLACE(w_CURRENTSTATIONTIME,'T',' '),REPLACE(w_CURRENTSTATIONPLANNEDTIME,'T',' '),w_TrainLONG,w_TrainLAT,w_CURRENTSTATIONDELAY,REPLACE(w_TRAINETD,'T',' '),REPlACE(w_TRAINETA,'T',' '),REPLACE(w_TRAINNEWETA,'T',' '));
        commit;          
       trace('TRANSIT','end insert');  

        update EDI_TRANSIT_UPDATE set processed = 'Y' where seq_no = processloop.seq_no; commit;

   end loop; 

END process_transit_data1;
/
我希望你能从中得到一个想法,因为它适合我。顺便说一下,我的JSON负载如下所示:

CREATE TABLE EDI_TRANSIT_UPDATE
(
  SEQ_NO            NUMBER,
  CREATED_DATE      DATE,
  CREATED_BY        VARCHAR2(20 BYTE),
  LAST_UPDATE_DATE  DATE,
  LAST_UPDATE_BY    VARCHAR2(20 BYTE),
  PROCESSED         VARCHAR2(1 BYTE)            DEFAULT 'N',
  CLOB              BLOB
);
{        "TRAIN_NO": "B1Z1002153250819",
        "CONSIGNMENT_NUMBER": "8094777054",
        "TRAIN_ORIGIN_NAME": "BELLVILLE",
        "TRAIN_ORIGIN_DATE": "2019-08-25T00:00:00",
        "CurrentStationTime": "2019-08-25T22:55:19",
        "CurrentStationPlannedTime": "2019-08-25T20:52:00",
        "TrainLONG": 19.66555008,
        "TrainLAT": -33.4827,
        "CurrentStationDelay": 123,
        "TrainETD": "2019-08-25T15:30:00",
        "TrainETA": "2019-08-26T04:40:00",
        "TrainNewETA": "2019-08-26T06:43:00"
    }

那么,真正的问题是什么?有更好的方法还是更有效的方法?