Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Rajesh.

Asked: February 27, 2018 - 3:40 pm UTC

Last updated: March 20, 2018 - 11:30 am UTC

Version: 12c

Viewed 1000+ times

You Asked

CREATE TABLE j_computerlist
  (computer_data CLOB CONSTRAINT ensure_json CHECK (computer_data IS JSON));

CREATE TABLE Mytable (
Computers varchar2(200),
Idnumber NUMBER(10),
Environment varchar2(200),
LastReportTime date,
firstcheckin date,
status_code varchar2(100)
);  
  
  INSERT INTO j_computerlist
  VALUES ('{
    "Computers": {
        "quebrada": [
            {
                "id": "927003",
                "environment": "iem-cis",
                "lastReportTime": "Tue, 27 Feb 2018 08:31:46 -0600",
                "ipAddress": "10.205.2.68,10.220.91.116",
                "locked": "False",
                "firstCheckin": "Wed, 24 Jun 2015 09:14:57 -0600",
                "lastUDPping": "Tue, 27 Feb 2018 08:00:27 -0600"
            }
        ],
        "quitaque": [
            {
                "id": "2220618",
                "environment": "iem-cis",
                "lastReportTime": "Tue, 27 Feb 2018 08:33:07 -0600",
                "ipAddress": "10.204.103.53",
                "locked": "False",
                "firstCheckin": "Fri, 14 Nov 2014 03:08:54 -0600",
                "lastUDPping": "Tue, 27 Feb 2018 07:59:53 -0600"
            }
        ],
        "quenemo": [
            {
                "id": "4091629",
                "environment": "iem-cis",
                "lastReportTime": "Tue, 27 Feb 2018 08:29:00 -0600",
                "ipAddress": "10.205.2.69,10.220.91.117",
                "locked": "False",
                "firstCheckin": "Wed, 24 Jun 2015 09:14:57 -0600",
                "lastUDPping": "Tue, 27 Feb 2018 08:00:19 -0600"
            }
        ]
    },
    "status_text": "",
    "error_text": "",
    "status_code": "200",
    "status": "OK",
    "rc": "0"
}');

commit;

insert into mytable 
????


How to get the key using JSON query and translate date data in appropriate format so I can insert data in mytable as follows

select * from mytable ;

computers    idnumber    environment LastReportTime  firstcheckin    status_code

quebrada    927003  iem-cis 27 Feb 2018 08:31:46    24 Jun 2015 03:14:57    200
quitaque    2220618 iem-cis 27 Feb 2018 08:33:07    13 Nov 2014 21:08:54    200
quenemo     4091629 iem-cis 27 Feb 2018 08:29:00    24 Jun 2015 03:14:57    200



and Chris said...

You can use JSON_table to convert documents into a relational structure.

BUT!

This extracts values. The computers (quebrada etc.) in the document are attributes.

You can pull the other values easily enough out using nested path, wildcarding the attribute:

select j.*
from   j_computerlist, json_table (
  computer_data, '$'
  columns (
    computers varchar2(10) path '$.computers',
    nested path '$.Computers.*'
    columns (
      pos            for ordinality,
      idnumber       varchar2(10) path '$.id',  
      environment    varchar2(10) path '$.environment',
      LastReportTime varchar2(40) path '$.lastReportTime',
      firstcheckin   varchar2(40) path '$.firstCheckin'
    ),
    status_code     varchar2(10) path '$.status_code'
  )
) j;

COMPUTERS   STATUS_CODE   POS   IDNUMBER   ENVIRONMENT   LASTREPORTTIME                    FIRSTCHECKIN                      
<null>      200               1 927003     iem-cis       Tue, 27 Feb 2018 08:31:46 -0600   Wed, 24 Jun 2015 09:14:57 -0600   
<null>      200               2 2220618    iem-cis       Tue, 27 Feb 2018 08:33:07 -0600   Fri, 14 Nov 2014 03:08:54 -0600   
<null>      200               3 4091629    iem-cis       Tue, 27 Feb 2018 08:29:00 -0600   Wed, 24 Jun 2015 09:14:57 -0600


"For ordinality" returns the position within the document. So if the computers are fixed you could use this to generate the names. But if you need to pull the computers out dynamically, it's tougher.

In PL/SQL you can use the get_keys method of json_object_t to extract attribute names. Sadly this doesn't work in SQL.

So you could build a function that accepts the document and the attribute position you want to extract. Then return the name of this:

create or replace function get_key ( pos int, json varchar2 ) 
  return varchar2 as
  jdoc     json_object_t;
  doc_keys json_key_list;
begin

  jdoc := json_object_t.parse ( json );
  
  doc_keys := treat ( jdoc.get('Computers') as json_object_t).get_keys;
  
  return doc_keys(pos);
end get_key;
/


You can then pass the ordinal column to this:

select get_key(pos, computer_data) computer, j.*
from   j_computerlist, json_table (
  computer_data
  columns (
    nested path '$.Computers.*'
    columns (
      pos for ordinality,
      id, environment, lastReportTime, firstCheckin
    ),
    status_code
  )
) j;

COMPUTER   POS   ID        ENVIRONMENT   LASTREPORTTIME                    FIRSTCHECKIN                      STATUS_CODE   
quebrada       1 927003    iem-cis       Tue, 27 Feb 2018 08:31:46 -0600   Wed, 24 Jun 2015 09:14:57 -0600   200           
quitaque       2 2220618   iem-cis       Tue, 27 Feb 2018 08:33:07 -0600   Fri, 14 Nov 2014 03:08:54 -0600   200           
quenemo        3 4091629   iem-cis       Tue, 27 Feb 2018 08:29:00 -0600   Wed, 24 Jun 2015 09:14:57 -0600   200 


If you have control of the JSON document, it would be better to change it so computer (names?) are values instead though. e.g.:

"name": "quenemo",
  "data": [
            {
                "id": "4091629",
                "environment": "iem-cis",
                "lastReportTime": "Tue, 27 Feb 2018 08:29:00 -0600",
                "ipAddress": "10.205.2.69,10.220.91.117",
                "locked": "False",
                "firstCheckin": "Wed, 24 Jun 2015 09:14:57 -0600",
                "lastUDPping": "Tue, 27 Feb 2018 08:00:19 -0600"
            }
        ]


This enables you to get all values with JSON_table. And avoid building the custom function!

Note in the last example above I've used 18c's simplified json_table syntax. This infers paths from the names:

https://livesql.oracle.com/apex/livesql/file/content_F81S3YX84C0VNUMFDJLFR3F1E.html

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Rajesh Pahade, March 19, 2018 - 10:59 am UTC

This solution is going to work only with 12.2 version.
Our database is running on 12.1. Do we have any alternate solution to json_object_t which will work in 12.1?
Chris Saxon
March 20, 2018 - 11:30 am UTC

More to Explore

SQL

The Oracle documentation contains a complete SQL reference.