2017-03-09 7 views
1

CLOB Json 열에서 키/값 쌍이있는 테이블을 얻을 수있는 방법이 있습니까?ORACLE - JSON 키 값 쌍 테이블

여기에있는 아이디어는 이러한 값을 동적으로 얻는 것입니다. CLOB 열은 항상 동일한 구조를 포함하지는 않기 때문입니다.

많은 레코드가있는 테이블에서 매우 느리게 사용할 때 json 문자열을 구문 분석하기 때문에이 작업을 수행하는 함수를 만들었습니다. 그리고 매우 느리게 나는 초당 2-5 레코드를 의미합니다. 나는 그것이 끔찍한 것을 압니다.

오라클 툴 (12.1c)은 json 태그/값을 동적으로 얻을 수있는 방법을 제공하지 않으므로 항상 경로를 지정해야합니다.

나는 행운도없이 주위를 파고 있었다. 이견있는 사람?

+0

"CLOB 열에 항상 같은 구조가있는 것은 아닙니다"라고 말하면 어떤 변형이 있습니까? – APC

+0

@APC 최악의 시나리오에서 행마다 다른 JSON 구조를 기대할 수 있습니다. 이 열은 다양한 소스로 채워지기 때문입니다. – bmvr

답변

2

12.2에는 JSON 문서의 DOM과 유사한 구조를 작성하는 데 사용할 수있는 PL/SQL 객체 세트가 포함되어 있습니다. 그런 다음 객체의 메소드를 사용하여 키 목록 등을 추출 할 수 있습니다. JSON_OBJECT_T의 12.2 문서에서 봐, JSON_ARRAY_T 등과 같이 사용할 수있는 ..

SQL> create or replace type NV_PAIR_T as object (
    2 NAME VARCHAR2(32), 
    3 VALUE VARCHAR2(32) 
    4 ) 
    5/

Type created. 

SQL> create or replace type NV_PAIR_TABLE as TABLE of NV_PAIR_T 
    2/

Type created. 

SQL> create or replace function GET_KEY_VALUES(P_JSON_DOC VARCHAR2) 
    2 return NV_PAIR_TABLE PIPELINED 
    3 as 
    4 JO JSON_OBJECT_T := JSON_OBJECT_T(P_JSON_DOC); 
    5 JO_KEYS JSON_KEY_LIST := JO.get_keys(); 
    6 begin 
    7 
    8 for i in 1..JO_KEYS.count loop 
    9  pipe row (NV_PAIR_T(JO_KEYS(i),JO.get_string(JO_KEYS(i)))); 
10 end loop; 
11 end; 
12/

Function created. 

SQL> select * 
    2 from TABLE(GET_KEY_VALUES('{"A":"AA", "B":"BB", "C":"CC"}')) 
    3/
A        AA 
B        BB 
C        CC 

SQL> 

다음은이 도움말을

+0

중첩 된 객체가있는 객체의 예를 들어주세요. 나는 현재 내 컴퓨터가 내 주변에 있지 않다. 그러나 이것이 효과가 있다면 나는 매우 행복 할 것이다! – bmvr

0

을하는 중첩 된 구조를 안내합니다 변형입니다.

SQL> drop FUNCTION PROCESS_JSON_DOCUMENT 
    2/

Function dropped. 

SQL> drop TYPE NV_PAIR_TABLE 
    2/

Type dropped. 

SQL> drop TYPE NV_PAIR_T 
    2/

Type dropped. 

SQL> create or replace TYPE NV_PAIR_T as object (
    2 JSON_PATH VARCHAR2(4000), 
    3 VALUE  VARCHAR2(4000) 
    4 ) 
    5/

Type created. 

SQL> create or replace TYPE NV_PAIR_TABLE 
    2 as TABLE of NV_PAIR_T 
    3/

Type created. 

SQL> create or replace FUNCTION PROCESS_JSON_DOCUMENT(P_JSON_PATH VARCHAR2, P_JSON_DOCUMENT VARCHAR2) 
    2 return NV_PAIR_TABLE PIPELINED 
    3 as 
    4 V_JSON_OBJECT JSON_OBJECT_T := JSON_OBJECT_T(P_JSON_DOCUMENT); 
    5 V_KEY_LIST  JSON_KEY_LIST := V_JSON_OBJECT.get_keys(); 
    6 V_KEY_NAME  VARCHAR2(4000); 
    7 V_JSON_PATH  VARCHAR2(4000); 
    8 V_CHILD_DOCUMENT VARCHAR2(4000); 
    9 begin 
10 for i in 1..V_KEY_LIST.count loop 
11  V_KEY_NAME := V_KEY_LIST(i); 
12  if (V_JSON_OBJECT.get_type(V_KEY_LIST(i)) <> 'OBJECT') then 
13   pipe row (NV_PAIR_T(P_JSON_PATH || '.' || V_KEY_NAME,V_JSON_OBJECT.get_string(V_KEY_NAME))); 
14  else 
15  V_JSON_PATH := P_JSON_PATH || '.' || V_KEY_NAME; 
16  V_CHILD_DOCUMENT := V_JSON_OBJECT.get_object(V_KEY_NAME).to_string(); 
17  for j in (select * from TABLE(PROCESS_JSON_DOCUMENT(V_JSON_PATH, V_CHILD_DOCUMENT))) loop 
18   pipe row (NV_PAIR_T(J.JSON_PATH,J.VALUE)); 
19  end loop; 
20  end if; 
21 end loop; 
22 end; 
23/

Function created. 

SQL> column JSON_PATH format A32 
SQL> column VALUE format A32 
SQL> select * 
    2 from TABLE(PROCESS_JSON_DOCUMENT('$','{"A":"AA", "B":"BB", "C":"CC", "X" : {"A":"AA", "B":"BB", "C":"CC"}}')) 
    3/
$.A        AA 
$.B        BB 
$.C        CC 
$.X.A       AA 
$.X.B       BB 
$.X.C       CC 

6 rows selected. 

SQL>