oracle 如何使用JSON_VALUE获取包含对象数组的嵌套数据

hmmo2u0o  于 2023-05-06  发布在  Oracle
关注(0)|答案(3)|浏览(425)

我有一个表MYTABLE,它有3列,如下所述。

|id | myclob_column | column3|

它有一个列(myclob_column),是clob数据(json)。样本clob数据如下。

{
"name" : "Rahul",
"address" : [ {"street" : "100"}, {"street" : "200"} .....]
}

我想从street值为'200'的表中获取所有行。
当我们硬编码职位时,下面的select query是有效的(在我们的例子[1]中):

select * from MYTABLE where JSON_VALUE(`myclob_column`, $.address[1].street) = '200';

但是我不能硬编码address的位置,因为值(200)可以在任何位置。因此,我需要一个通用查询来匹配任何位置的street为200。我尝试了很多事情,但都做不到。

bzzcjhmw

bzzcjhmw1#

您可以使用json_table将JSON数据转换为表中的行和列:

select  t.*
from mytable t, json_table( myclob_column , '$.address[*]'
                COLUMNS (street PATH '$.street')
               )
where STREET = 200

Demo here

v9tzhpje

v9tzhpje2#

您可以解析JSON值并添加条件,而无需硬编码,如下所示,

select 
  * 
from 
mytable t1, 
JSON_TABLE(t1.clob_column,'$.address[*]' 
           COLUMNS 
           (STREET varchar PATH '$.street')
) t2 
where t2.street = '200';

你可以看到实时的sql here

rseugnpd

rseugnpd3#

你可以在数组元素上使用json_exists和 predicate :

SQL> with sample as (
  2    select 1 as id, to_clob('{
  3      "name" : "Rahul",
  4      "address" : [ {"street" : "100"}, {"street" : "200"}]
  5      }') as val from dual
  6    union all
  7    select 2 as id, to_clob('{
  8      "name" : "Rahul",
  9       "address" : [ {"street" : "100"}, {"street" : "300"}]
 10    }') as val from dual 
 11  )
 12  select
 13    sample.*
 14  from sample
 15  where json_exists(val, '$.address[*]?(@.street == "200")')

        ID VAL                                                                             
---------- --------------------------------------------------------------------------------
         1 {                                                                               
               "name" : "Rahul",                                                           
               "address" : [ {"street" : "100"}, {"street" : "200"}

UPD:如果你想使用json_tablewhere过滤器,那么最好使用exists predicate 或使用横向连接和一个访问表的子查询,如果有多行需要值,不要分解结果集。

假设这个样本数据(还有一个street: 200条目):

create table sample as
  select 1 as id, to_clob('{
    "name" : "Rahul",
    "address" : [ {"street" : "100"}, {"street" : "200"}, {"street": "200"}]
    }') as val from dual
  union all
  select 2 as id, to_clob('{
    "name" : "Rahul",
     "address" : [ {"street" : "100"}, {"street" : "300"}]
  }') as val from dual

交叉连接:

select
  sample.*
from sample,
    json_table(
      val
      , '$.address[*]'
      columns (street PATH '$.street')
    ) flt
where flt.street = '200'
ID瓦尔
1我 “name”:“Rahul”, “address”:[ {“street”:“100”},{“street”:“200”},{“street”:“200”} {\fnSimHei\bord1\shad1\pos(200,288)}
1我 “name”:“Rahul”, “address”:[ {“street”:“100”},{“street”:“200”},{“street”:“200”} {\fnSimHei\bord1\shad1\pos(200,288)}

exists

select
  sample.*
from sample
where exists (
    select null
    from json_table(
      val
      , '$.address[*]'
      columns (street PATH '$.street')
    )
    where street = '200'
  )

cross join lateral,带子查询:

select
  sample.*
from sample
  cross join lateral (
    select null
    from json_table(
      val
      , '$.address[*]'
      columns (street PATH '$.street')
    )
    where street = '200'
      and rownum = 1
  )
ID瓦尔
1我 “name”:“Rahul”, “address”:[ {“street”:“100”},{“street”:“200”},{“street”:“200”} {\fnSimHei\bord1\shad1\pos(200,288)}

fiddle

相关问题