简体   繁体   English

oracle sql 中的 JSON_TABLE 未捕获的嵌套 json 数据

[英]Nested json data not captured by JSON_TABLE in oracle sql

I'm using Oracle 12c(12.2) to read json data in a table.我正在使用 Oracle 12c(12.2) 读取表中的 json 数据。

SELECT        jt.name,
jt.employee_id, 
jt.company    
FROM JSON_TABLE ( BFILENAME ('DB_DIR', 'vv.json')

i've nested data in json output.我在 json output 中嵌套了数据。 The key:value in nested data start with a value "past_work": "NA" for a record.嵌套数据中的 key:value 以记录的值"past_work": "NA" for other many records below it, have actual values like对于它下面的其他许多记录,具有实际值,例如

"past_work": [{ "company": "XXXXX",   "title": "XXXX"}]

but because first record done have value and start and end brackets [], oracle not capturing below records nested values.但是因为完成的第一条记录具有值以及开始和结束括号 [],oracle 没有捕获下面的记录嵌套值。 any idea how to capture below records?知道如何捕获以下记录吗?

Example: Actual data like below示例:如下所示的实际数据

  SELECT
      jt.company,
      jt.title
    FROM
      JSON_TABLE(
        '{
           "employee_data": [
             { "employee_id": "111",
               "past_work": "N/A"
             },
             { "employee_id": "222",
               "past_work": [
                 {"company": "XXXXX", "title": "XXXX"},
                 {"company": "YYYYY", "title": "YYYY"}
               ]
             },
             { "employee_id": "333",
               "past_work": [
                 {"company": "XXXXX", "title": "XXXX"},
                 {"company": "YYYYY", "title": "YYYY"}
                ]
             }
           ]
         }',
        '$.past_work[*]'
          COLUMNS (
            company VARCHAR2(100) PATH '$.company',
            title   VARCHAR2(100) PATH '$.title'
          )
      )
        AS jt

now when i execute above statment, i'm getting null for company values for emplyee_id 333 and below.现在,当我执行上述语句时,我得到 null 用于 emplyee_id 333 及以下的公司价值。

Thanks谢谢

If past_work is supposed to be an array of past (company, title) pairs, then the proper way to encode "no history" is not to use a string value like "N/A" , but instead you should use an empty array, as I show in the code below.如果past_work应该是一个过去(company, title)对的数组,那么编码“no history”的正确方法是不要使用像"N/A"这样的字符串值,而是应该使用一个空数组,正如我在下面的代码中所示。 If you do it your way, you can still extract the data, but it will be exceptionally messy.如果你按照自己的方式去做,你仍然可以提取数据,但它会异常混乱。 If you use JSON, use it correctly.如果您使用JSON,请正确使用。

Also, you said you want to extract company and title.另外,你说你想提取公司和头衔。 Just those?就这些? That makes no sense.这是没有意义的。 Rather, you probably want to extract the employee id for each employee, along with the work history.相反,您可能希望提取每个员工的员工 ID 以及工作历史。 In the work history, I add a column "for ordinality" (to show which company was first, which was second, etc.) If you don't need it, just leave it out.在工作历史中,我添加了一个“for ordinality”列(以显示哪个公司是第一个,哪个是第二个等)如果您不需要它,只需将其省略即可。

To access nested columns, you must use the nested clause in the columns specification.要访问嵌套列,您必须使用columns规范中的nested子句。

select employee_id, ord, company, title
from   json_table(
        '{
           "employee_data": [
             { "employee_id": "111",
               "past_work": [ ]
             },
             { "employee_id": "222",
               "past_work": [
                 {"company": "XXXXX", "title": "XXXX"},
                 {"company": "YYYYY", "title": "YYYY"}
               ]
             },
             { "employee_id": "333",
               "past_work": [
                 {"company": "XXXXX", "title": "XXXX"},
                 {"company": "YYYYY", "title": "YYYY"}
                ]
             }
           ]
         }',   '$.employee_data[*]'
               columns ( 
                         employee_id varchar2(10) path '$.employee_id',
                           nested path '$.past_work[*]'
                               columns (
                                         ord     for ordinality,
                                         company varchar2(10) path '$.company',
                                         title   varchar2(10) path '$.title'
                                       )
                       )
       ) jt
order by employee_id, ord;

Output: Output:

EMPLOYEE_ID ORD COMPANY TITLE
----------- --- ------- -----
111                          
222           1 XXXXX   XXXX 
222           2 YYYYY   YYYY 
333           1 XXXXX   XXXX 
333           2 YYYYY   YYYY 

First, the json snippet is malformed, it MUST be surrounded by {} in order to be parsable as a json object...首先,json 代码段格式不正确,它必须被{}包围才能被解析为 json object...

  • {"past_work": [{ "company": "XXXXX", "title": "XXXX"}]}

Then, you can tell the json parser that you want to pull the rows from the past_work element...然后,您可以告诉 json 解析器您要从past_work元素中提取行...

  • JSON_TABLE(<yourJsonString>, '$.past_work[*]')

The [*] tells the parser that past_work is an array, and to process that array in to rows of json objects, rather than just return the whole array as a single json object. [*]告诉解析器past_work是一个数组,并将该数组处理为 json 对象的行,而不是将整个数组作为单个 json object 返回。

That gives something like...这给出了类似...

SELECT
  jt.company,
  jt.title
FROM
  JSON_TABLE(
    '{
        "past_work": [
            {"company": "XXXXX", "title": "XXXX"},
            {"company": "YYYYY", "title": "YYYY"}
        ]
     }',
    '$.past_work[*]'
      COLUMNS (
        company VARCHAR2(100) PATH '$.company',
        title   VARCHAR2(100) PATH '$.title'
      )
  )
    AS jt

db<>fiddle demo db<>小提琴演示


For more details, I recommend reading the docs:有关更多详细信息,我建议阅读文档:


EDIT: Updated example, almost a copy and paste from the docs编辑:更新的示例,几乎是文档中的复制和粘贴

  • Please Read The Docs!请阅读文档!

SELECT
  jt.*
FROM
  JSON_TABLE(
    '{
        "XX_data":[
          {
            "employee_id": "E1",
            "full_name":   "E1  Admin",
            "past_work":   "N/A"
          },
          {
            "employee_id": "E2",
            "full_name":   "E2  Admin",
            "past_work": [
              {"company": "E2 PW1 C", "title": "E2 PW1 T"},
              {"company": "E2 PW2 C", "title": "E2 PW2 T"},
            ]
          },
        ]
     }',
    '$.XX_data[*]'
      COLUMNS (
        employee_id VARCHAR2(100) PATH '$.employee_id',
        full_name   VARCHAR2(100) PATH '$.full_name',
        past_work   VARCHAR2(100) PATH '$.past_work',
        NESTED PATH '$.past_work[*]'
          COLUMNS (
            past_work_company VARCHAR2(100) PATH '$.company',
            past_work_title   VARCHAR2(100) PATH '$.title'
          )
      )
  )
    AS jt

Another db<>fiddle demo 另一个 db<>fiddle 演示

Thanks all for the Comments.感谢大家的评论。 Have asked product team to provide data in correct format.已要求产品团队提供正确格式的数据。

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

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