1. 程式人生 > >oracle12C資料庫JSON的應用 --PL/SQL儲存過程中JSON解析應用篇

oracle12C資料庫JSON的應用 --PL/SQL儲存過程中JSON解析應用篇

最近有些專案在資料庫oracle中使用到json格式的資料互動,對於oracle12以上的版本都支援JSON格式資料的使用,剛剛接觸的猿們可以到上一篇oracle資料庫使用json的簡單入門,最好參考官方的API文件關於oracle官方API文件對JSON的支援
下面就比較詳細的說一下,關於oracle資料庫在儲存過程中的JSON解析應用:
一:先上一段儲存過程解析JSON的儲存過程,看你們能不能看的懂。
看不懂沒關係,後面我會慢慢的分析怎麼解析json。

/*  JSON_IN 的json格式(僅供參考):   
  {
    "procedureNameFlag": "xxx",
    "param_in": [{
      "PROD_PLANT": "xxx",
      "MODEL_NAME": "xxx"
    }],
    "doAfter": "xxx",
    "tableName": "xxx",
    "tableIndex": "xxx",
    "curSchema": "xxx",
    "funCode": "xxx",
    "ObjI_Button": "xxx",
    "empNo": "xxx"
  }*/
CREATE OR REPLACE PROCEDURE  PRC_JSON_TEST(JSON_IN    IN VARCHAR2, RES_OUT     OUT VARCHAR2)  IS
  JSON_OBJ             JSN;
  PARAM_IN_LIST        JSN_LIST;
  PARAM_OBJ            JSN;
  PROD_PLANT_P         C_EMP_T.PLANT%TYPE;
  MODEL_NAME_P         C_NAME_T.NAME%TYPE;
  cnt_p                NUMBER(10);
  LOCATION_P VARCHAR2(10);
  OPERATE_P VARCHAR2(10);
  PROD_CATEGORY_NAME_p VARCHAR2(40);
  O_PROD_CATEGORY_NAME_p VARCHAR2(40);
  I NUMBER(5);
begin
  RES_OUT := '{"RES":"OK","MSG":""}';
  --解析JSON引數
  BEGIN
    JSON_OBJ := JSN(JSON_IN);
    IF NOT
        ((REPLACE(JSON_OBJ.get('procedureNameFlag').TO_CHAR, '"', '') = 'doAfter') AND
        ((REPLACE(JSON_OBJ.get('ObjI_Button').TO_CHAR, '"', '') = 'ADD') OR
         (REPLACE(JSON_OBJ.get('ObjI_Button').TO_CHAR, '"', '') = 'UPDATE'))) THEN
        IF NOT
            ((REPLACE(JSON_OBJ.get('procedureNameFlag').TO_CHAR, '"', '') = 'doBefore') AND
            (REPLACE(JSON_OBJ.get('ObjI_Button').TO_CHAR, '"', '') = 'ADD' )) THEN      
          RETURN;
        END IF;     
     END IF;
    LOCATION_P := REPLACE(JSON_OBJ.get('procedureNameFlag').TO_CHAR, '"', '');    
    OPERATE_P := REPLACE(JSON_OBJ.get('ObjI_Button').TO_CHAR, '"', '');
    PARAM_IN_LIST := JSN_LIST(JSON_OBJ.get('param_in').TO_CHAR); 
    I := 1;
    WHILE I <= PARAM_IN_LIST.COUNT LOOP
      --PARAM_OBJ := JSN(JSON_OBJ.get('param_in').TO_CHAR);
      PARAM_OBJ := JSN(PARAM_IN_LIST.GET(I).TO_CHAR);
      MODEL_NAME_P := PARAM_OBJ.get('MODEL_NAME').TO_CHAR;
      MODEL_NAME_P := REPLACE(MODEL_NAME_P, '"', '');
      PROD_PLANT_P := PARAM_OBJ.get('PROD_PLANT').TO_CHAR;
      PROD_PLANT_P := REPLACE(PROD_PLANT_P, '"', '');
      PROD_CATEGORY_NAME_P := PARAM_OBJ.get('PROD_CATEGORY_NAME').TO_CHAR;
      PROD_CATEGORY_NAME_P := REPLACE(PROD_CATEGORY_NAME_P, '"', ''); 
      IF ((LOCATION_P='doAfter') AND (OPERATE_P='ADD')) THEN
        BEGIN
          SELECT count(model_name)
            INTO cnt_p
            FROM C_MODEL_DESC_T A
           WHERE A.MODEL_NAME = MODEL_NAME_P AND ROWNUM=1;
          IF cnt_p=0 THEN
              INSERT INTO C_MODEL_DESC_T
                (MODEL_NAME, CREATE_EMP)
                SELECT A.MODEL_NAME, A.CREATE_EMP
                  FROM C_PROD_PLANT_MODEL_T A
                 WHERE PROD_PLANT = PROD_PLANT_P
                   AND MODEL_NAME = MODEL_NAME_P;
          END IF;
        EXCEPTION
          WHEN OTHERS THEN
           DELETE FROM C_PROD_PLANT_MODEL_T A
                 WHERE PROD_PLANT = PROD_PLANT_P
                   AND MODEL_NAME = MODEL_NAME_P;
        END;
            UPDATE C_PROD_PLANT_MODEL_T
            SET PROD_CATEGORY_NAME = PROD_CATEGORY_NAME_P
            WHERE MODEL_NAME = MODEL_NAME_P
            AND PROD_CATEGORY_NAME IS NULL;    
        COMMIT;
      ELSIF ((LOCATION_P='doAfter') AND (OPERATE_P='UPDATE')) THEN  
        BEGIN
          SELECT PROD_CATEGORY_NAME 
          INTO O_PROD_CATEGORY_NAME_p 
          FROM C_PROD_PLANT_MODEL_T
          WHERE MODEL_NAME = MODEL_NAME_P
          AND PROD_CATEGORY_NAME IS NOT NULL
          AND ROWNUM = 1;
          IF O_PROD_CATEGORY_NAME_P <> PROD_CATEGORY_NAME_P THEN
            UPDATE C_PROD_PLANT_MODEL_T
            SET PROD_CATEGORY_NAME = PROD_CATEGORY_NAME_P
            WHERE MODEL_NAME = MODEL_NAME_P;
          ELSE 
            UPDATE C_PROD_PLANT_MODEL_T
            SET PROD_CATEGORY_NAME = PROD_CATEGORY_NAME_P
            WHERE MODEL_NAME = MODEL_NAME_P
            AND PROD_CATEGORY_NAME IS NULL;         
          END IF;
        EXCEPTION
          WHEN NO_DATA_FOUND THEN
            UPDATE C_PROD_PLANT_MODEL_T
            SET PROD_CATEGORY_NAME = PROD_CATEGORY_NAME_P
            WHERE MODEL_NAME = MODEL_NAME_P
            AND PROD_CATEGORY_NAME IS NULL;    
        END;    
        COMMIT;
      ELSIF ((LOCATION_P='doBefore') AND (OPERATE_P='ADD')) THEN  
        BEGIN
          SELECT PROD_CATEGORY_NAME 
          INTO O_PROD_CATEGORY_NAME_p 
          FROM C_PROD_PLANT_MODEL_T
          WHERE MODEL_NAME = MODEL_NAME_P
          AND PROD_CATEGORY_NAME IS NOT NULL
          AND ROWNUM = 1;
          IF O_PROD_CATEGORY_NAME_P <> PROD_CATEGORY_NAME_P THEN
            RES_O := '{"RES":"NG","MSG":"Prod Category must be '||O_PROD_CATEGORY_NAME_P||'"}';
            RETURN;
          END IF;
        EXCEPTION
          WHEN NO_DATA_FOUND THEN
            RETURN;
        END; 
      END IF;      
      I := I+1;
    END LOOP;    
  EXCEPTION
    WHEN OTHERS THEN
      --RES_O := '{"RES":"NG","MSG":"Input Parameters Error!"}';
      RES_O := '{"RES":"NG","MSG":"ORACLE ERROR:' ||
             REPLACE(dbms_utility.format_error_backtrace(), '"', '') || '"}';
      ROLLBACK;
      RETURN;
  END;
end;

二.詳細解析在oracle中使用json
從簡單的說起。。。
1.先建立一個儲存過程:

CREATE OR REPLACE PROCEDURE PRC_JSON_TEST(param_in    IN VARCHAR2, result_out  OUT VARCHAR2)

包含兩個引數,一個IN引數:用來接受傳入json格式字串資料的引數;一個OUT引數:用來返回輸出執行儲存過程之後的結果資訊。
2.宣告變數,用於接受解析json變數(需要根據自己實際需要去宣告變數)

  count             BINARY_INTEGER;                            --宣告一個有符號整型變數count
  json_obj      JSN;                                                     --宣告一個JSON物件變數json_obj
  param_obj     JSN;                                                   --宣告一個JSON物件變數param_obj
  KIND_NAME_V   C_DUTY_T.KIND_NAME%TYPE;  --宣告一個型別是某張表某個欄位型別屬性的變數
  PARAM_IN_LIST JSN_LIST;                                     --宣告一個JSON陣列變數
  i NUMBER(5);

說明一下:param_in傳入的JSON字元資料的引數,其格式可以包含多種(基本的格式只有兩種,一種是json陣列,另一種是json物件;兩者可以相互巢狀),有JSONArray巢狀JSONObject或相互巢狀、或JSONObject中的value值又巢狀JSONObject或JSONArray等等。本次我使用的json格式是JSONObject中的value巢狀JSONArray和JSONObject:

 /*  param_in 傳入的json引數*/
  {
    "param_in": [{
      "PROD": "CA00",
      "NAME": "123123"
    }],
    "name": "tiger",
    "age": "one",
    "sex": "1",
    "address": "232",
  }

3.解析json過程,實現自己的功能邏輯

--解析傳入json格式字串並賦值給json物件變數,使用JSN()解析
json_obj :=JSN(param_in);

--使用get()方法獲取json_obj中key對應的value值,其value值是個json陣列列表,使用JSN_LIST()解析
PARAM_IN_LIST  :=JSN_LIST(json_obj.get('param_in').TO_CHAR);

--獲取json陣列下標為1的值,其值是json物件,使用JSN()解析;
param_obj  :=JSN(PARAM_IN_LIST.GET(1).TO_CHAR);

--當然如果是json陣列多個值的話,可以使用迴圈遍歷,下面使用 WHILE ..LOOP..方法,你也可以使用FOR..IN(..)...LOOP方法遍歷
--PARAM_IN_LIST.COUNT獲取json陣列的長度
WHILE i<=PARAM_IN_LIST.COUNT LOOP
     --自己的邏輯功能
     END LOOP

後面就可以參考上面的基本方法,回頭自己研究上上面的儲存過程了