Oracle JSON_OBJECT NULL ON NULL 子句不起作用
Oracle JSON_OBJECT NULL ON NULL clause not working
我正在尝试让 Oracle 在 SQL NULL
数据上生成 JSON null
值,如下所示:
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;
或者:
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;
不幸的是,这两个查询都会导致:
|C1 |C2 |
|----------|----------|
|{"a":1} |{"a":1} |
我本以为会是这样:
|C1 |C2 |
|-------------------|----------|
|{"a":1,"b":null} |{"a":1} |
我错过了什么?我正在使用 Oracle XE 18c
你有一个小的变化来获得值:
select
json_object(key 'a' value 1, key 'b' value null ) c1,
json_object(key 'a' value 1 ) c2
from dual;
结果是
C1: C2:
{"a":1,"b":null} {"a":1}
Oracle 处理 JSON_OBJECT
的方式似乎存在错误,它将从语句中的最后一个 JSON_on_null_clause
获取参数并将其应用于所有 JSON_OBJECT
表达式:
CREATE TABLE t ( a,b ) AS
SELECT 1, null FROM DUAL UNION ALL
SELECT 2, 'bb' FROM DUAL;
如果你这样做:
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;
则输出为:
C1 | C2
:--------------- | :---------------
{"a":1} | {"a":1}
{"a":2,"b":"bb"} | {"a":2,"b":"bb"}
如果用相反的表达式执行相同的查询:
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;
则输出为:
C2 | C1
:--------------- | :---------------
{"a":1,"b":null} | {"a":1,"b":null}
{"a":2,"b":"bb"} | {"a":2,"b":"bb"}
db<>fiddle here
这对我来说像是一个错误:
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
输出:
+-------------------+---------+
| C1 | C2 |
+-------------------+---------+
| {"a":1,"b":null} | {"a":1} |
+-------------------+---------+
当用 (SELECT exp FROM dual)
包装更改结果集 () 时,这是这些奇怪的事件之一。
我猜是某种优化机制("common subexpression elimination")导致 exp 在 first/last 出现后被评估。如果您更改密钥,它可以正常工作:
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;
您发现了一个错误。
我已备案
错误 31013529 - 两个 JSON_OBJECT 具有不同的 NULL 处理程序 RETURN 错误结果
我们会尽快修复它并将其包含在捆绑补丁中。
如果您需要一次性补丁,请告诉我们
谢谢
b
郑重声明,其他功能也受到影响,例如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;
产量:
|C1 |C2 |
|----------|----------|
|[1] |[1] |
而此解决方法...
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;
产生正确的结果:
|C2 |C1 |
|----------|----------|
|[1] |[1,null] |
我正在尝试让 Oracle 在 SQL NULL
数据上生成 JSON null
值,如下所示:
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;
或者:
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;
不幸的是,这两个查询都会导致:
|C1 |C2 |
|----------|----------|
|{"a":1} |{"a":1} |
我本以为会是这样:
|C1 |C2 |
|-------------------|----------|
|{"a":1,"b":null} |{"a":1} |
我错过了什么?我正在使用 Oracle XE 18c
你有一个小的变化来获得值:
select
json_object(key 'a' value 1, key 'b' value null ) c1,
json_object(key 'a' value 1 ) c2
from dual;
结果是 C1: C2: {"a":1,"b":null} {"a":1}
Oracle 处理 JSON_OBJECT
的方式似乎存在错误,它将从语句中的最后一个 JSON_on_null_clause
获取参数并将其应用于所有 JSON_OBJECT
表达式:
CREATE TABLE t ( a,b ) AS
SELECT 1, null FROM DUAL UNION ALL
SELECT 2, 'bb' FROM DUAL;
如果你这样做:
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;
则输出为:
C1 | C2 :--------------- | :--------------- {"a":1} | {"a":1} {"a":2,"b":"bb"} | {"a":2,"b":"bb"}
如果用相反的表达式执行相同的查询:
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;
则输出为:
C2 | C1 :--------------- | :--------------- {"a":1,"b":null} | {"a":1,"b":null} {"a":2,"b":"bb"} | {"a":2,"b":"bb"}
db<>fiddle here
这对我来说像是一个错误:
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
输出:
+-------------------+---------+
| C1 | C2 |
+-------------------+---------+
| {"a":1,"b":null} | {"a":1} |
+-------------------+---------+
当用 (SELECT exp FROM dual)
包装更改结果集 (
我猜是某种优化机制("common subexpression elimination")导致 exp 在 first/last 出现后被评估。如果您更改密钥,它可以正常工作:
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;
您发现了一个错误。 我已备案 错误 31013529 - 两个 JSON_OBJECT 具有不同的 NULL 处理程序 RETURN 错误结果
我们会尽快修复它并将其包含在捆绑补丁中。 如果您需要一次性补丁,请告诉我们
谢谢 b
郑重声明,其他功能也受到影响,例如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;
产量:
|C1 |C2 |
|----------|----------|
|[1] |[1] |
而此解决方法...
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;
产生正确的结果:
|C2 |C1 |
|----------|----------|
|[1] |[1,null] |