简体   繁体   English

使用 Oracle SQL 解析 Json - JSON_TABLE

[英]Parse Json using Oracle SQL - JSON_TABLE

I am trying to parse JSON using JSON_TABLE.我正在尝试使用 JSON_TABLE 解析 JSON。

Oracle DB version 12.1.0.2 Oracle DB版本12.1.0.2

{
 "Rownum": "1",
 "Name": "John",
 "AddressArray":["Address1", "Address2"],
 "TextObj":[{
             "mName" : "Carol",
             "lName" : "Cena"
            },
            {
             "mName" : "Mark",
             "lName" : "Karlo"
            }
           ]
}

Tried with below query but not getting expected result.尝试使用以下查询但未获得预期结果。

select * from json_Table(
'{
 "Rownum": "1",
 "Name": "John",
 "AddressArray":["Address1", "Address2"],
 "TextObj":[{"mName" : "Carol","lName" : "Cena"},
            {"mName" : "Mark","lName" : "Karlo"}
           ]
}', 
'$' columns (  rownr number path '$.Rownum', 
               name varchar2(100) path '$.Name', 
               nested path '$.TextObj[*]' columns  (mName varchar2(100) path '$.mName',
                                                    lName varchar2(100) path '$.lName'
                                                    ),
               nested path '$.AddressArray[*]' columns(AddressArray varchar2(100) path '$')
             )
);

Output from above query: Output 来自上述查询:

在此处输入图像描述

Expected output:预期 output:

在此处输入图像描述

You could chain several json_table calls:您可以链接几个json_table调用:

select j1.rnum, j1.name, j2.address, j3.mName, j3.lName
from (
  select '{
 "Rownum": "1",
 "Name": "John",
 "AddressArray":["Address1", "Address2"],
 "TextObj":[{
             "mName" : "Carol",
             "lName" : "Cena"
            },
            {
             "mName" : "Mark",
             "lName" : "Karlo"
            }
           ]
}' as str
  from dual
) t
outer apply json_table (
  t.str format json, '$'
  columns (
    rNum number path '$.Rownum',
    name varchar2(10) path '$.Name',
    addressArray varchar2(4000) format json path '$.AddressArray',
    textObj varchar2(4000) format json path '$.TextObj'
  )
) j1
outer apply json_table (
  j1.addressArray, '$[*]'
  columns (
    address varchar2(10) path '$'
  )
) j2
outer apply json_table (
  j1.textObj, '$[*]'
  columns (
    mName varchar2(10) path '$.mName',
    lName varchar2(10) path '$.lName'
  )
) j3

where t is just an inline view to supply your sample JSON as a str column, which is then processed by the first json_table .其中t只是一个内联视图,用于提供您的示例 JSON 作为str列,然后由第一个json_table处理。 That gets the rownumber and name values, and also the address array which is passed to the second json_table , and the text object which is passed to the third json_table .这将获取行号和名称值,以及传递给第二个json_table的地址数组,以及传递给第三个 json_table 的文本json_table Those produce the values from their arrays.这些从他们的 arrays 中产生值。

RNUM | NAME | ADDRESS  | MNAME | LNAME
---: | :--- | :------- | :---- | :----
   1 | John | Address1 | Carol | Cena 
   1 | John | Address1 | Mark  | Karlo
   1 | John | Address2 | Carol | Cena 
   1 | John | Address2 | Mark  | Karlo

db<>fiddle (18c, but verified on 12cR1). db<>fiddle (18c,但在 12cR1 上验证)。

You seem to want a cross join of the array values (grouped by rownum and name ).您似乎想要数组值的交叉连接(按rownumname分组)。 This is not a standard JSON structure, so you shouldn't expect to be able to do this with a single application of json_table .这不是标准的 JSON 结构,因此您不应该期望能够通过json_table的单个应用程序来做到这一点。

Here is one way to do this with two calls to json_table .这是通过两次调用json_table来做到这一点的一种方法。 In the first call, you use a nested path to get just the names, but you still keep the address arrays.在第一次调用中,您使用嵌套路径仅获取名称,但仍保留地址 arrays。 In a second call, you unpack the addresses, separately for each row produced by the first call.在第二次调用中,您为第一次调用生成的每一行分别解包地址。

Note the use of an optimizer hint in the outer select .请注意在外部select中使用优化器提示。 This is needed, because without it the optimizer will try an illegal "unnesting" of the lateral join ( outer apply ) and then throw an error, instead of leaving the query as is.这是必需的,因为没有它,优化器将尝试对横向连接( outer apply )进行非法的“取消嵌套”,然后抛出错误,而不是让查询保持原样。 (This is a very common and annoying habit of the optimizer: it tries something that is invalid, and then it complains about it.) (这是优化器的一个非常常见且令人讨厌的习惯:它尝试一些无效的东西,然后抱怨它。)

Also, rownum is a reserved keyword - you can't use it as a column name in the output.此外, rownum是保留关键字 - 您不能将其用作 output 中的列名。 (Technically you can, with additional work, but it is best to believe that you can't.) (从技术上讲,你可以通过额外的工作,但最好相信你不能。)

with
  t as (
    select * 
    from   json_Table(
'{
 "Rownum": "1",
 "Name": "John",
 "AddressArray":["Address1", "Address2"],
 "TextObj":[{"mName" : "Carol","lName" : "Cena"},
            {"mName" : "Mark","lName" : "Karlo"}
           ]
}', 
           '$' columns (
                 rownr        number                     path '$.Rownum', 
                 name         varchar2(100)              path '$.Name', 
                 addressArray varchar2(4000) format json path '$.AddressArray',
                 nested path '$.TextObj[*]'
                   columns  (mName varchar2(100) path '$.mName',
                             lName varchar2(100) path '$.lName'
                            )
               )
           )
  )
select /*+ no_query_transformation */ rownr, name, mname, lname, address
from t
     outer apply
     json_table (t.addressArray, '$[*]'
                   columns (address varchar2(10) path '$')
     )
;

Output: Output:

ROWNR NAME   MNAME  LNAME  ADDRESS   
----- ------ ------ ------ ----------
    1 John   Carol  Cena   Address1  
    1 John   Carol  Cena   Address2  
    1 John   Mark   Karlo  Address1  
    1 John   Mark   Karlo  Address2 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM