在 Oracle 中搜索 JSON 数组
Search a JSON array in Oracle
我正在尝试使用 Oracle 12.1.0.2
中引入的新 JSON 功能
但是,我似乎无法找到在我的 JSON 文档中的数组中查找特定值的方法。
考虑以下 table 和数据:
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 查询,其中 return 包含订购产品 #2 的所有订单。
我不能使用 json_exists
因为它不允许数组表达式(而且我也不知道如何指定值)。
json_value
只有 return 一个值,所以我不能 "iterate" 遍历数组值。
我试过了:
select *
from orders o
where json_value(details, '$.products[*].product') = '2';
但这并没有 return 任何东西。
我也试过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”中的 "star expansion" 不会扩展 json_table
中的值
所以我的问题是:
如何(根据上述示例数据)检索所有订购了编号为2的产品的订单?
我实际上是在寻找与此 Postgres 查询等效的内容:
select *
from orders
where details @> '{"products": [{"product": 2}] }';
我现在没有任何可用的 oracle 安装,但我相信 json_table 中的第一个字符串应该是我们要从中生成行的数组的路径。
然后在 COLUMNS 中,路径应该是相对于数组的,而不是根。
试试这个:
select *
from orders o,
json_table(o.details, '$.products[*]'
columns (
product_id integer path '$.product'
)
) t
where t.product_id = 2;
在 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>
我正在尝试使用 Oracle 12.1.0.2
中引入的新 JSON 功能但是,我似乎无法找到在我的 JSON 文档中的数组中查找特定值的方法。
考虑以下 table 和数据:
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 查询,其中 return 包含订购产品 #2 的所有订单。
我不能使用 json_exists
因为它不允许数组表达式(而且我也不知道如何指定值)。
json_value
只有 return 一个值,所以我不能 "iterate" 遍历数组值。
我试过了:
select *
from orders o
where json_value(details, '$.products[*].product') = '2';
但这并没有 return 任何东西。
我也试过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”中的 "star expansion" 不会扩展 json_table
所以我的问题是:
如何(根据上述示例数据)检索所有订购了编号为2的产品的订单?
我实际上是在寻找与此 Postgres 查询等效的内容:
select *
from orders
where details @> '{"products": [{"product": 2}] }';
我现在没有任何可用的 oracle 安装,但我相信 json_table 中的第一个字符串应该是我们要从中生成行的数组的路径。 然后在 COLUMNS 中,路径应该是相对于数组的,而不是根。
试试这个:
select *
from orders o,
json_table(o.details, '$.products[*]'
columns (
product_id integer path '$.product'
)
) t
where t.product_id = 2;
在 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>