Oracle12.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"}');
ここで、製品#2が注文されたすべての注文を返すSQLクエリを作成しようとしています。
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}] }';
現在、利用可能な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>