10

I have googled aplenty, and can't seem to find a simple solution to my simple use case. I have a json column in an Oracle 12C database (actually a varchar with json constraint of course), and in that column I store a representation of a Map like this

{
"a":9.0847,
"b":859.947
}

In plsql I would like to return a result set of that looks like this

key val
a   9.0847
b   859.947

I have tinkered with seemingly infinite variations of this below, and all the examples are too contrived for my use case.

select b.* from mytable a,json_table(myJsonCol,'$'
columns ( value varchar2(500) path '$.myjsonkey')) b

but this only returns a list of values, without the corresponding keys. The json data is ALWAYS string-double key vals.

thanks

EDIT To add a bit more context, i use json_each in postgres to do this now, and i'm looking for a similar method in Oracle.

5
  • What is the solution for this ? Commented Oct 4, 2018 at 17:25
  • @RaviShankar i never found one, had to keep track of keys by various object types and use that separately Commented Oct 4, 2018 at 21:06
  • How did you do that? Were you able to get all the keys in a single column? Commented Oct 5, 2018 at 4:25
  • @RaviShankar no, we ended up storing the keys in another table, but your idea of having a column to store them would probably accomplish the same.. problem is keeping them consistent Commented Oct 5, 2018 at 12:23
  • Possibly, You can use the terminology as given in the link: link Commented Jun 18, 2019 at 5:28

4 Answers 4

2

Here's a generic solution that I tried on 18c and 21c, which uses PL/SQL APIs from within a SQL WITH function to produce the desired output (you can, of course, also store the function):

with
  function json_keys(j varchar2) return clob as
    jo json_object_t;
    k json_key_list;
    r clob;
  begin
    jo := json_object_t(j);
    k := jo.get_keys();
    select coalesce(
      json_arrayagg(column_value returning clob),
      json_array(returning clob)
    )
    into r
    from table (k);
    return r;
  end;
select o, json_keys(o)
from (
  select '{}' as o from dual union all
  select '{"a":1}' from dual union all
  select '{"a":1,"b":2}' from dual
) t;

Resulting in:

|O            |JSON_KEYS(O)|
|-------------|------------|
|{}           |[]          |
|{"a":1}      |["a"]       |
|{"a":1,"b":2}|["a","b"]   |
Sign up to request clarification or add additional context in comments.

2 Comments

Danke, welche Version von Oracle benutzt du? (what version of oracle are you using)
@MarkGiaconia: I tried this on 18c and 21c, not on 12c. There have been tons of more recent JSON improvements, so it might be that this doesn't yet work on 12c... Although, the json_object_t type is already described in 12c, so you might get a solution similar to this to work on your installation, too: docs.oracle.com/en/database/oracle/oracle-database/12.2/arpls/…
1

Try this:

declare
  jo JSON_OBJECT_T;
  i  NUMBER;
  keys JSON_KEY_LIST;
  CURSOR c_json IS
     SELECT myJsonCol FROM mytable;
begin
  FOR rec IN c_json
  LOOP
     jo := JSON_OBJECT_T.parse(rec.myJsonCol);
     keys := jo.get_keys;
     dbms_output.put_line('KEY VAL');
     FOR i in 1..keys.COUNT
     LOOP
        dbms_output.put_line(keys(i) || ' ' || jo.get_Number(keys(i)));
     END LOOP;
   END LOOP;
END;
/

Comments

0

Your JSON value is a single tuple, so you could use UNPIVOT to turn it into a table of key/value pairs:

with mydata as (
  select '{
  "a":9.0847,
  "b":859.947
  }' myjsoncol
  from dual
), q as (
  select json_value(mydata.myjsoncol, '$.a') ca
        ,json_value(mydata.myjsoncol, '$.b') cb
  from mydata
) select * from q
unpivot (val for key in (ca as 'a', cb as 'b'));

KEY VAL
=== =======
a   9.0847
b   859.947

Live SQL: https://livesql.oracle.com/apex/livesql/s/d31n9re90y6cpghi4i3m9hfoh

1 Comment

thanks, but the problem is I can't know that a and b exist as keys....all the data has potentially different fields as the key in the map.
-2

For Oracle 11g version Json manupulation is not supported. So we must use basic functions : SUBSTR / INSTR / SUBSTR

Check solution on another thread : Manipulating JSON data with SQL in Oracle

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.