web-dev-qa-db-ja.com

PL / SQLを使用してJSONをOracleテーブルに解析する

Oracle SQL DeveloperからMobile App DB(MongoDBに基づく)からデータを読み取るために、次のスクリプトを作成しました。

 DECLARE 
 l_param_list VARCHAR2(512); 
 
 l_http_request UTL_HTTP.req; 
 l_http_response UTL_HTTP.resp; 
 
 l_response_text VARCHAR2(32767); 
 BEGIN 
 
-サービスの入力パラメーター
 
-リクエストの準備... 
 l_http_request:= UTL_HTTP.begin_request( 'https://api.appery.io/rest/1/db/collections/Photos?where=%7B%22Oracle_Flag%22%3A%22Y%22%7D'
、「GET」
、「HTTP/1.1」); 
 
-...ヘッダーの属性を設定
 UTL_HTTP.set_header(l_http_request、 'X- Appery-Database-Id '、' 53f2dac5e4b02cca64021dbe '); 
 --UTL_HTTP.set_header(l_http_request、' Content-Length '、LENGTH(l_param_list)); 
 
-。 ..set入力パラメータ
-UTL_HTTP.write_text(l_http_request、l_param_list); 
 
-応答を取得し、受信値を取得
 l_http_response:= UTL_HTTP.ge t_response(l_http_request); 
 
 UTL_HTTP.read_text(l_http_response、l_response_text); 
 
 DBMS_OUTPUT.put_line(l_response_text); 
 Appery値に挿入(l_response_text); 
-ファイナライズ
 UTL_HTTP.end_response(l_http_response); 
 
 
 EXCEPTION 
 WHEN UTL_HTTP.end_of_body 
 THEN UTL_HTTP.end_response(l_http_response); 
終わり;
/

応答(l_response_text)はJSONのような文字列です。例えば:

[{"Postcode": "47100"、 "OutletCode": "128039251"、 "MobileNumber": "0123071303"、 "_ createdAt": "2014-11-10 06:12:49.837"、 "_ updatedAt": "2014- 11-10 06:12:49.837 "}、{" Postcode ":" 32100 "、" OutletCode ":" 118034251 "、.....]

コードは正常に機能し、応答をapperyという1つの列テーブルに挿入します。ただし、各配列がappery_testと呼ばれるテーブルの特定の列に入るように、この応答を解析する必要があります。テーブルappery_testには、JSONペアの数と同じ順序で同じ数の列があります。

検索してみたところ、OracleテーブルをJSONに解析した結果のほとんどが見つかりました。しかし、私は this リンクを見つけましたが、これは私の問題に多少似ています。ただし、回答で提案されているライブラリには、PL/SQLを使用して従来のテーブルにJSONを挿入するための使用方法に関する例がありません。

N.B.:12cではなく11gを使用しています。したがって、 built in 関数は利用できません。

14
Hawk

PL/JSONライブラリ を使用しました。具体的には、JSON_EXTパッケージはそれを解析するために機能します。

Oracle Communityの回答に触発された次のスクリプトは私のために働いた

 DECLARE 
 l_param_list VARCHAR2(512); 
 
 l_http_request UTL_HTTP.req; 
 l_http_response UTL_HTTP.resp; 
 
 l_response_text VARCHAR2(32767); 
 
 l_list json_list; 
 A_id VARCHAR2(200); 
 UserId VARCHAR2(100); 
 UserName VARCHAR2 (100); 
 OutletCode VARCHAR2(100); 
 OutletName VARCHAR2(100); 
 MobileNumber VARCHAR2(100); 
 PhoneNumber VARCHAR2(100); 
 Address VARCHAR2(100); 
 City VARCHAR2(100); 
 State VARCHAR2(100); 
 Postcode VARCHAR2(100); 
 Email VARCHAR2( 100); 
 UpdateCount VARCHAR2(100); 
 loginCount VARCHAR2(100); 
 ReferencePhoto VARCHAR2(100); 
 Updates VARCHAR2(100); 
 AccountLocked VARCHAR2(100); 
 Oracle_Flag VARCHAR2(100); 
 acl VARCHAR2(100); 
 
 
 BEGIN 
 
-サービスの入力pa rameters 
 
-リクエストを準備しています... 
 l_http_request:= UTL_HTTP.begin_request( 'https://api.appery.io/rest/1/db/collections/Outlet_Details ?where =%7B%22Oracle_Flag%22%3A%22Y%22%7D '
、' GET '
、' HTTP/1.1 '); 
 
 -...ヘッダーの属性を設定
 UTL_HTTP.set_header(l_http_request、 'X-Appery-Database-Id'、 '53f2dac5e4b02cca64021dbe'); 
 --UTL_HTTP.set_header(l_http_request、 'Content- Length '、LENGTH(l_param_list)); 
 
-...入力パラメーターの設定
-UTL_HTTP.write_text(l_http_request、l_param_list); 
 
-応答を取得し、受信した値を取得
 l_http_response:= UTL_HTTP.get_response(l_http_request); 
 
 UTL_HTTP.read_text(l_http_response、l_response_text); 
 
 DBMS_OUTPUT.put_line(l_response_text); 
 l_list:= json_list(l_response_text); 
 
 FOR i IN 1..l_list.count 
 LOOP 
 A_id:= json_ext.get_string(json(l_list.get(i))、 '_ id'); 
 UserId:= json_ext.get_string(json(l_list.get (i))、 'UserId'); 
 UserName:= json_ext.get_string(json(l_list.get(i))、 'UserName'); 
 OutletCode:= json_ext.get_string(json (l_list.get(i))、 'OutletCode'); 
 OutletName:= json_ext.get_string(json(l_list.get(i))、 'OutletName'); 
 MobileNumber:= json_ext .get_string(json(l_list.get(i))、 'MobileNumber'); 
 PhoneNumber:= json_ext.get_string(json(l_list.get(i))、 'PhoneNumber'); 
住所:= json_ext.get_string(json(l_list.get(i))、 'Address'); 
市:= json_ext.get_string(json(l_list.get(i))、 'City'); 
状態:= json_ext.get_string(json(l_list.get(i))、 'State'); 
郵便番号:= json_ext.get_string(json(l_list.get(i))、 'Postcode '); 
メール:= json_ext.get_string(json(l_list.get(i))、' Email '); 
 UpdateCount:= json_ex t.get_string(json(l_list.get(i))、 'UpdateCount'); 
 loginCount:= json_ext.get_string(json(l_list.get(i))、 'loginCount'); 
 ReferencePhoto:= json_ext.get_string(json(l_list.get(i))、 'ReferencePhoto'); 
 Updates:= json_ext.get_string(json(l_list.get(i))、 'Updates'); 
 AccountLocked:= json_ext.get_string(json(l_list.get(i))、 'AccountLocked'); 
 Oracle_Flag:= json_ext.get_string(json(l_list.get(i))、 ' Oracle_Flag '); 
 acl:= json_ext.get_string(json(l_list.get(i))、' acl '); 
 
 
 insert ... .. 

json_ext.get_stringは、最大32767に制限されたVARCHAR2のみを再チューニングすることに注意してください。同じパッケージをより大きなjson_listおよびjson_values(> 32KB)で使用するには、 here を確認してください。

APEX 5.0以降を使用している場合は、 APEX_JSON パッケージを使用して、より優れたオプションとはるかに優れたパフォーマンスを実現できます。詳細については、@ Olafur Tryggvason の回答を参照してください

8
Hawk

この質問の結果は高得点であるため、この推奨代替案を投稿したいと思います。

Oracleは APEX 5. (2015年4月15日)をリリースしました。これにより、JSONを操作するための優れたAPIにアクセスできます

私は11.2でそれを使用しており、複数の配列と4/5レベルを持つ単純なオブジェクトから非常に複雑なオブジェクトまで、すべてのjsonを処理することができました。 APEX_JSON

APEXを使用したくない場合。ランタイム環境をインストールするだけで、APIにアクセスできます。

サンプルの使用法、 json.orgの例 のデータ:

declare
    sample_json   varchar2 (32767)
        := '{
    "glossary": {
        "title": "example glossary",
        "GlossDiv": {
            "title": "S",
            "GlossList": {
                "GlossEntry": {
                    "ID": "SGML",
                    "SortAs": "SGML",
                    "GlossTerm": "Standard Generalized Markup Language",
                    "Acronym": "SGML",
                    "Abbrev": "ISO 8879:1986",
                    "GlossDef": {
                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
                        "GlossSeeAlso": ["GML", "XML"]
                    },
                    "GlossSee": "markup"
                }
            }
        }
    }
}';
begin
    apex_json.parse (sample_json);
    dbms_output.put_line (apex_json.get_varchar2 ('glossary.GlossDiv.title'));
    dbms_output.put_line (apex_json.get_varchar2 ('glossary.GlossDiv.GlossList.GlossEntry.GlossTerm'));
    dbms_output.put_line (apex_json.get_varchar2 ('glossary.GlossDiv.GlossList.GlossEntry.GlossDef.GlossSeeAlso[%d]', 2));
end;

結果:実行されたPL/SQLブロック

S
Standard Generalized Markup Language
XML
14

Oraceは、JSON処理用のPL/SQL DOM APIを提供します。多数の有用なAPIが提供されるため、使用することを強くお勧めします。

https://docs.Oracle.com/database/122/ADJSN/using-PLSQL-object-types-for-JSON.htm#GUID-F0561593-D0B9-44EA-9C8C-ACB6AA9474EE

1
Srikrishnan

oracle 12の場合: https://docs.Oracle.com/database/121/SQLRF/functions092.htm#SQLRF5697

SELECT jt.*
FROM j_purchaseorder,
JSON_TABLE(po_document, '$.ShippingInstructions.Phone[*]'
COLUMNS (row_number FOR ORDINALITY,
         phone_type VARCHAR2(10) PATH '$.type',
         phone_num VARCHAR2(20) PATH '$.number'))
AS jt;

ROW_NUMBER PHONE_TYPE PHONE_NUM
---------- ---------- --------------------
         1 Office     909-555-7307
         2 Mobile     415-555-1234
0
Z. Anton