问题 在Oracle中搜索JSON数组


我正在尝试使用Oracle 12.1.0.2中引入的新JSON功能

但是我似乎找不到在JSON文档中查找数组中特定值的方法。

请考虑以下表格和数据:

create table orders
(
   id      integer not null primary key,
   details clob not null check (details is json (strict))
);

insert into orders (id, details) values 
(1, '{"products": [{ "product": 1, "quantity": 5}, {"product": 2, "quantity": 1}], "delivery_address": "My hometown"}');

insert into orders (id, details) values 
(2, '{"products": [{ "product": 42, "quantity": 1}, {"product": 10, "quantity": 2}], "comment": "Your website is too slow"}');

insert into orders (id, details) values 
(3, '{"products": [{ "product": 543, "quantity": 1}], "discount": "15"}');

insert into orders (id, details) values 
(4, '{"products": [{ "product": 738, "quantity": 12}], "discount": "32"}');

现在我正在尝试编写一个返回所有订单的SQL查询,其中订购了产品#2。

我不能用 json_exists 因为它不允许数组表达式(我不知道如何指定值)。

json_value 只返回一个值,所以我不能“迭代”数组值。

我试过了:

select *
from orders o
where json_value(details, '$.products[*].product') = '2';

但这没有任何回报。

我也试过了 json_table,但这似乎只采取数组中的第一个元素:

select *
from orders o, 
     json_table(o.details, '$' columns (product_id integer path '$.products[*].product')) t
where t.product_id = 2;

但这并没有表现出什么。显然是“明星扩张”中的“array_step“不会扩大价值观 json_table

所以我的问题是:

我如何(根据上面的示例数据)检索订购了数字2的产品的所有订单?

我基本上寻找相当于这个Postgres查询:

select *
from orders
where details @> '{"products": [{"product": 2}] }';

1587
2018-04-27 14:37


起源

运行JSON_TABLE函数时遇到了多线程错误。基本上,当同时运行两个JSON_TABLE时,其中一个会话断开连接。在使用JSON进行全部操作之前,请确保已对其进行了修补。 - Peter Henell
@PeterHenell:谢谢你的提示。目前我只是在探索各种可能性,但我会牢记这一点。 - a_horse_with_no_name


答案:


我现在没有任何oracle安装,但我相信json_table中的第一个字符串应该是我们想要从中生成行的数组的路径。 然后在里面 ,路径应该是相对于数组,而不是根。

尝试这个:

select *
from orders o, 
     json_table(o.details, '$.products[*]' 
         columns (
              product_id integer path '$.product'
         )
     ) t
where t.product_id = 2;

15
2018-04-27 14:57



啊!这就是诀窍。 - a_horse_with_no_name
我们可以更新现有阵列吗?我们可以将产品对象添加到ID为1的订单的产品数组中吗? - Somesh Gupta


在12.2中,您可以使用JSON_EXISTS执行此操作

 SQL> WITH ORDERS as
   2  (
   3    select 1 as ID, '{"products": [{ "product": 1, "quantity": 5}, {"product": 2, "quantity": 1}], "delivery_address": "My hometown"}' as DETAILS
   4      from dual
   5    union all
   6    select 2 as ID, '{"products": [{ "product": 42, "quantity": 1}, {"product": 10, "quantity": 2}], "comment": "Your website is too slow"}' as DETAILS
   7      from dual
   8    union all
   9    select 3 as ID, '{"products": [{ "product": 543, "quantity": 1}], "discount": "15"}' as DETAILS
  10      from dual
  11    union all
  12    select 4 as ID, '{"products": [{ "product": 738, "quantity": 12}], "discount": "32"}' as DETAILS
  13     from dual
  14  )
  15  select *
  16    from ORDERS
  17   where JSON_EXISTS(DETAILS,'$?(@.products.product == $PRODUCT)' passing 2 as "PRODUCT")
  18  /

         ID
 ----------
 DETAILS
 --------------------------------------------------------------------------------
          1
 {"products": [{ "product": 1, "quantity": 5}, {"product": 2, "quantity": 1}], "d
 elivery_address": "My hometown"}


 SQL>

0
2018-06-12 21:00



Actualy json_exist在12.1中使用相同的功能,但不使用indexex - Alexander Tokarev