使用PL / SQL将JSON解析为Oracle表

Parse JSON into Oracle table using PL/SQL

我创建了以下脚本,以便从Oracle SQL Developer从Mobile App DB(基于MongoDB)读取数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
DECLARE
  l_param_list     VARCHAR2(512);

  l_http_request   UTL_HTTP.req;
  l_http_response  UTL_HTTP.resp;

  l_response_text  VARCHAR2(32767);
BEGIN

  -- service's input parameters

  -- preparing Request...
  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');

  -- ...set header's attributes
  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 input parameters
 -- UTL_HTTP.write_text(l_http_request, l_param_list);

  -- get Response and obtain received value
  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);
  INSERT INTO appery VALUES(l_response_text);
  -- finalizing
  UTL_HTTP.end_response(l_http_response);


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

响应(l_response_text)是类似JSON的字符串。 例如:

1
[{"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的列表中。 但是,我需要解析此响应,以便每个数组进入名为appery_test的表中的特定列。 表appery_test的列数与JSON对数相同,并且顺序相同。

我进行了搜索,发现有关将Oracle表解析为JSON的大多数结果,而并非相反。 不过,我发现此链接与我的问题有些相似。 但是,答案中建议的库没有有关如何使用它通过PL / SQL将JSON插入常规表的任何示例。

N.B .:我使用的是11g,而不是12c。 因此内置功能对我不可用。


由于此问题的评分很高,因此我想发布以下首选的替代方法:

Oracle已发布APEX 5.0(2015年4月15日)。有了它,您就可以访问使用JSON的出色API

我在11.2上使用了它,并且能够处理每个json,从具有多个数组和4/5级的简单对象到非常复杂的对象。 APEX_JSON

如果您不想使用APEX。只需安装运行时环境即可访问API。

用法示例,数据来自json.org的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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块

1
2
3
S
Standard Generalized Markup LANGUAGE
XML

我使用PL / JSON库。具体来说,JSON_EXT包用于解析它。

以下受Oracle Community Answer启发的脚本对我有用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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

  -- service's input parameters

  -- preparing Request...
  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');

  -- ...set header's attributes
  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 input parameters
 -- UTL_HTTP.write_text(l_http_request, l_param_list);

  -- get Response and obtain received value
  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');
  Address        := json_ext.get_string(json(l_list.get(i)),'Address');
  City           := json_ext.get_string(json(l_list.get(i)),'City');
  State          := json_ext.get_string(json(l_list.get(i)),'State');
  Postcode       := json_ext.get_string(json(l_list.get(i)),'Postcode');
  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');
  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)使用相同的包,请在此处检查。

如果您拥有APEX 5.0及更高版本,则可以通过APEX_JSON软件包获得更好的选择和更好的性能。有关详细信息,请参见@Olafur Tryggvason的答案


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


在Oracle 12中:
https://docs.oracle.com/database/121/SQLRF/functions092.htm#SQLRF56973

1
2
3
4
5
6
7
8
9
10
11
12
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