【问题标题】:Generating json file from table in Oracle PL/SQL从 Oracle PL/SQL 中的表生成 json 文件
【发布时间】:2020-08-22 12:16:07
【问题描述】:

我在表格中有以下表格中的数据。

我想生成以下格式的数据。

{
    "delete": [
        {
            "canonicalName": "TCS"          
        }
    ],
    "update": [
         {
            "canonicalName": "Wipro tech"
            "synonyms": [
                "Wipro technology"
            ]
         },
         {
            "canonicalName": "Infosys"
            "synonyms": [
                "Infosys tech"
            ]
         }
    ]       
    "add": [
        {
            "canonicalName": "Apple Computers",
            "synonyms": [
                "Apple"
            ]
        },
        {
            "canonicalName": "Google India",
            "synonyms": ["Google"]
        }
    ]
}

我可以使用一些库和 POJO 类在 java 中编写相同的代码。我可以在 Oracle PL/SQL 中创建任何可能性吗?早些时候我从 jdbc 读取数据并在 java 代码中创建这个文件。现在我必须将此代码保留为 pl/sql 过程的一部分。无论如何我可以生成上述格式的数据吗?

【问题讨论】:

  • 你的 oracle 版本是什么?是 >=12.2 吗?
  • 假设您还有一行,ORGNAME = 'Apple Computers',SYNONYMS = 'Apple Inc',OPERATION = 'add'。在这种情况下,所需的结构是什么? canonicalName = 'Apple Computers' 的两个不同元素是否会出现在“add”的数组中,每个元素都只有一个同义词?还是会将它们组合成一个具有 canonicalName = 'Apple Computers' 的元素,并将所有同义词收集到一个(可能的多元素)同义词数组中?
  • @SayanMalakshinov 是的,它是 18c
  • 规范名称是唯一的

标签: json oracle plsql oracle12c


【解决方案1】:

如果您的数据库版本是12cR2+,那么您可以将json_objectagg()json_object()json_array()函数一起用作

SELECT json_query(
       json_objectagg
                 ( operation VALUE 
                   json_array(json_object('canonicalName' VALUE orgname,
                                          'synonyms'      VALUE json_array(synonyms) ) ) ),
       '$' returning VARCHAR2(4000) pretty )
    AS "Result JSON" 
  FROM tab

不要忘记添加json_query( ... , '$' returning VARCHAR2(4000) pretty ) 包裹整个表达式以获得漂亮的外观。

Demo

【讨论】:

  • 如果我的假设(如下所述)是正确的,那么您的解决方案并不完全正确。即:假设在输入中,对于相同的“操作”和相同的“组织名称”,有几个同义词。然后我假设(OP 需要澄清)"synonyms" 属性必须是单个数组,聚合该组织的所有同义词。在您的解决方案中,相同的orgname 将在同一个“操作”下多次出现。
【解决方案2】:

在您的输出中,当一个组织只有一个规范名称(没有同义词)时,您会显示只有一个属性的对应对象,即规范名称。如果您允许 "synonyms" 属性在所有情况下都存在会更容易 - 相应的数组可以为空 - 但这不是您在所需输出中显示的内容。

如果您允许空数组作为 "synonyms" 的值,那么 Barbaros Ozhan 已经提供了解决方案。 编辑 经检查,这可能并不完全正确;该解决方案不会将单个组织的同义词聚合到单个数组中(具有两个或多个同义词),而是将它们显示为不同的对象。请参阅下面我添加到我的答案中的示例数据。 结束编辑

此处进行大量编辑我正在添加示例数据以进行测试。我假设如果一个组织有两个或多个同义词(在同一个操作下),那应该导致操作数组的单个成员(规范名称只出现一次,具有两个或多个同义词的数组)。

我也修改了我的解决方案 - 找到了一种更简单的方法。通过点击答案下方的“已编辑”链接,可以看到对解决方案的更改。

测试数据:

drop table t purge;
create table t (orgname, synonyms, operation) as
  select 'Apple Computers', 'Apple'           , 'add'    from dual union all
  select 'Apple Computers', 'Apple Inc'       , 'add'    from dual union all
  select 'Google India'   , 'Google'          , 'add'    from dual union all
  select 'Wipro Tech'     , 'Wipro Technology', 'update' from dual union all
  select 'Infosys'        , 'Infosys Tech'    , 'update' from dual union all
  select 'TCS'            , null              , 'delete' from dual union all
  select 'IBM'            , null              , 'delete' from dual union all
  select 'IBM'            , 'IBM Corporation' , 'delete' from dual union all
  select 'IBM'            , 'IBM Corporation' , 'add'    from dual
;

查询:

with
  prep (operation, orgname, fragment) as (
    select operation, orgname,
           json_object( key 'canonicalName' value orgname,
                        key 'synonyms'
              value nullif(json_arrayagg(synonyms order by synonyms), '[]')
                                  FORMAT JSON  ABSENT ON NULL
                      )
     from   t
     group  by orgname, operation
   )
select json_objectagg( key operation
                       value json_arrayagg(fragment order by orgname)
                     ) as json_str
from   prep
group  by operation
;

输出(漂亮的打印):

{
  "add" :
  [
    {
      "canonicalName" : "Apple Computers",
      "synonyms" :
      [
    "Apple",
    "Apple Inc"
      ]
    },
    {
      "canonicalName" : "Google India",
      "synonyms" :
      [
    "Google"
      ]
    },
    {
      "canonicalName" : "IBM",
      "synonyms" :
      [
    "IBM Corporation"
      ]
    }
  ],
  "delete" :
  [
    {
      "canonicalName" : "IBM",
      "synonyms" :
      [
    "IBM Corporation"
      ]
    },
    {
      "canonicalName" : "TCS"
    }
  ],
  "update" :
  [
    {
      "canonicalName" : "Infosys",
      "synonyms" :
      [
    "Infosys Tech"
      ]
    },
    {
      "canonicalName" : "Wipro Tech",
      "synonyms" :
      [
    "Wipro Technology"
      ]
    }
  ]
}

【讨论】:

  • 首先非常感谢@mathguy 提供了这么棒的答案。情况是可以有多个同义词,如果同义词为空,我们可以删除同义词选项卡,
  • 嗨@Mathguy 我已经稍微扩展了我的要求。你的解决方案对我来说是完美的。你能帮我做些改变吗? stackoverflow.com/questions/63541003/…
猜你喜欢
  • 2010-12-21
  • 1970-01-01
  • 1970-01-01
  • 2020-03-31
  • 2017-01-01
  • 2012-04-19
  • 1970-01-01
  • 2015-08-15
  • 1970-01-01
相关资源
最近更新 更多