Reputation: 221135
I'm trying to get Oracle to produce JSON null
values on SQL NULL
data, as follows:
select
json_object(key 'a' value 1, key 'b' value null null on null) c1,
json_object(key 'a' value 1, key 'b' value null absent on null) c2
from dual;
Or also:
select
json_object(key 'a' value a, key 'b' value b null on null) c1,
json_object(key 'a' value a, key 'b' value b absent on null) c2
from (
select 1 a, null b
from dual
) t;
Unfortunately, both queries result in:
|C1 |C2 |
|----------|----------|
|{"a":1} |{"a":1} |
I would have expected this, instead:
|C1 |C2 |
|-------------------|----------|
|{"a":1,"b":null} |{"a":1} |
What am I missing? I'm using Oracle XE 18c
Upvotes: 3
Views: 9932
Reputation: 221135
Lukasz's answer provides a viable workaround using a correlated subquery.
For the record, other functions are also affected, e.g. JSON_ARRAYAGG
:
select
json_arrayagg(a null on null) c1,
json_arrayagg(a absent on null) c2
from (
select 1 a from dual union all select null a from dual
) t;
Yields:
|C1 |C2 |
|----------|----------|
|[1] |[1] |
Whereas this workaround...
select
cast(json_arrayagg((select a from dual) absent on null) as varchar2(10)) c2,
cast(json_arrayagg((select a from dual) null on null) as varchar2(10)) c1
from (
select 1 a from dual union all select null a from dual
) t;
Produces the correct result:
|C2 |C1 |
|----------|----------|
|[1] |[1,null] |
Upvotes: 2
Reputation: 436
you found a bug. I have filed Bug 31013529 - TWO JSON_OBJECT WITH DIFFERENT ON NULL HANDLER RETURN WRONG RESULTS
We'll fix it asap and include it in the bundle patches. Let us know if you need a one off patch
thanks b
Upvotes: 3
Reputation: 176014
It looks like a bug for me:
select
json_object(key 'a' value 1, key 'b' value null null on null) c1
,(SELECT json_object(key 'a' value 1, key 'b' value null absent on null) FROM dual) c2
from dual
Output:
+-------------------+---------+
| C1 | C2 |
+-------------------+---------+
| {"a":1,"b":null} | {"a":1} |
+-------------------+---------+
It is one of these strange occurences when wrapping with (SELECT exp FROM dual)
changes the resultset (https://stackoverflow.com/a/52561721/5070879).
I guess it is some optimization mechanism("common subexpression elimination") that causes the exp is evaluated once taking the first/last occurence. If you change the key it is working fine:
select
json_object(key 'a' value 1, key 'b' value null null on null) c1,
json_object(key 'a' value 1, key 'c' value null absent on null) c2
from dual;
Upvotes: 2
Reputation: 168371
There appears to be a bug on how Oracle handles JSON_OBJECT
and it will take the parameter from the last JSON_on_null_clause
in the statement and apply it to all of the JSON_OBJECT
expressions:
CREATE TABLE t ( a,b ) AS
SELECT 1, null FROM DUAL UNION ALL
SELECT 2, 'bb' FROM DUAL;
If you do this:
select json_object(
KEY 'a' VALUE a,
KEY 'b' VALUE b null on null
) c1,
json_object(
KEY 'a' VALUE a,
KEY 'b' VALUE b absent on null
) c2
from t;
Then the output is:
C1 | C2 :--------------- | :--------------- {"a":1} | {"a":1} {"a":2,"b":"bb"} | {"a":2,"b":"bb"}
If you perform the same query with the expressions reversed:
select json_object(
KEY 'a' VALUE a,
KEY 'b' VALUE b absent on null
) c2,
json_object(
KEY 'a' VALUE a,
KEY 'b' VALUE b null on null
) c1
from t;
Then the output is:
C2 | C1 :--------------- | :--------------- {"a":1,"b":null} | {"a":1,"b":null} {"a":2,"b":"bb"} | {"a":2,"b":"bb"}
db<>fiddle here
Upvotes: 3
Reputation: 37
you have a small change in order to get the values:
select
json_object(key 'a' value 1, key 'b' value null ) c1,
json_object(key 'a' value 1 ) c2
from dual;
The result is C1: C2: {"a":1,"b":null} {"a":1}
Upvotes: 0