web-dev-qa-db-fra.com

Analyser JSON dans une table Oracle à l'aide de PL/SQL

J'ai créé le script suivant afin de lire les données de la base de données Mobile App (basée sur MongoDB) à partir d'Oracle SQL Developer:

DÉCLARER
 l_param_list VARCHAR2 (512); 

 l_http_request UTL_HTTP.req; 
 l_http_response UTL_HTTP.resp; 

 l_response_text VARCHAR2 (32767); 
 BEGIN 

 - paramètres d'entrée du service 

 - préparation de la demande ...
 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 '); 

 - ... définir les attributs de l'en-tête 
 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)); ;________. - ... régler les paramètres d'entrée 
 - UTL_HTTP.write_text (l_http_request, l_param_list); 

 - obtenir une réponse et obtenir une valeur reçue 
 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); 
 insérer dans les valeurs d'appery (l_response_text); 
 - finaliser 
 UTL_HTTP.end_response (l_http_response); 


 EXCEPTION 
 WHEN UTL_HTTP.end_of_body 
 THEN UTL_HTTP.end_response (l_http_response); 
FIN;
/

La réponse (l_response_text) est une chaîne semblable à JSON. Par exemple:

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

Le code fonctionne correctement et insère la réponse dans une table-colonnes appelée appery. Cependant, je dois analyser cette réponse de sorte que chaque tableau entre dans sa colonne spécifique dans une table appelée appery_test. La table appery_test a un nombre de colonnes identique au nombre de paires JSON et dans le même ordre.

J'ai cherché et j'ai trouvé la plupart des résultats sur l'analyse de la table Oracle en JSON et non l'inverse. J'ai trouvé, cependant, ce lien qui est un peu similaire à mon problème. Cependant, la bibliothèque suggérée dans la réponse ne contient aucun exemple d'utilisation de JSON dans une table conventionnelle à l'aide de PL/SQL. 

N.B .: J'utilise 11g et non 12c. Donc, les fonctions intégrées ne sont pas disponibles pour moi.

14
Hawk

J'ai utilisé librairie PL/JSON . Plus précisément, le package JSON_EXT fonctionne afin de l’analyser. 

Le script suivant inspiré par Oracle Community answer a fonctionné pour moi

DÉCLARER
 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); 
 Nom d'utilisateur VARCHAR2 (100); 
 OutletCode VARCHAR2 (100) ; 
 OutletName VARCHAR2 (100); 
 MobileNumber VARCHAR2 (100); 
 Numéro de téléphone VARCHAR2 (100); 
 Adresse VARCHAR2 (100); 
 Ville VARCHAR2 (100); .__ État VARCHAR2 (100); 
 Code postal VARCHAR2 (100); 
 Email VARCHAR2 (100); 
 UpdateCount VARCHAR2 (100); 
 LoginCount VARCHAR2 (100); 
 RéférencePhoto VARCHAR2 (100); 
 Met à jour VARCHAR2 (100); 
 AccountLocked VARCHAR2 (100); 
 Oracle_Flag VARCHAR2 (100); 
 Acl VARCHAR2 (100); 


 COMMENCE 
 __. - paramètres d'entrée du service 

 - préparation de la demande ...
 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 '); 

 - ... définir les attributs de l'en-tête 
 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)); ;________. - ... régler les paramètres d'entrée 
 - UTL_HTTP.write_text (l_http_request, l_param_list); 

 - obtenir une réponse et obtenir une valeur reçue 
 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); 

 POUR 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'); 
 Nom d'utilisateur: = json_ext.get_string (json (l_list.get (i)), 'Nom d'utilisateur'); 
 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'); 
 Address: = json_ext.get_string (json (l_list.get (i)), 'Adresse'); 
 Ville: = json_ext.get_string (json (l_list.get (i)), 'Ville'); 
 State: = json_ext.get_string (json (l_list.get (i)), 'State'); 
 Code postal: = json_ext.get_string (json (l_list.get (i)), 'Code postal'); 
 Email: = json_ext.get_string (json (l_list.get (i)), 'Email'); 
 UpdateCount: = json_ext.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'); 
 Mises à jour: = 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'); 


 insérer .....

Notez que json_ext.get_string ne redémarre que VARCHAR2 limité à 32767 max. Pour utiliser le même package avec les plus grandes listes json_list et json_values ​​(> 32 Ko), vérifiez ici .

Si vous avez APEX 5.0 et versions ultérieures, meilleure option et performances bien meilleures via APEX_JSON package. Voir la réponse de @ Olafur Tryggvason pour les détails

8
Hawk

Étant donné que cette question a des résultats élevés, je souhaite publier cette alternative préférée:

Oracle a publié APEX 5.0 (15 avril 2015). Avec cela, vous avez accès à une excellente API pour travailler avec JSON 

Je l’utilise sur 11.2 et j’ai été en mesure de traiter chaque objet json de manière simple, des objets les plus simples aux plus complexes avec plusieurs tableaux et 4/5 niveaux. APEX_JSON

Si vous ne voulez pas utiliser APEX. Installez simplement l'environnement d'exécution pour accéder à l'API.

Exemple d'utilisation, données de exemple de 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;

Résultat: Bloc PL/SQL exécuté

S
Standard Generalized Markup Language
XML
13
Olafur Tryggvason

Orace fournit des API DOM PL/SQL pour la gestion JSON. Nous vous recommandons vivement de l’utiliser, car il fournit des tonnes d’API utiles.

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

1
Srikrishnan

dans Oracle 12: https://docs.Oracle.com/database/121/SQLRF/functions092.htm#SQLRF56973

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