从 Oracle PL/SQL 中的表生成 json 文件

Posted

技术标签:

【中文标题】从 Oracle PL/SQL 中的表生成 json 文件【英文标题】:Generating json file from table in Oracle PL/SQL 【发布时间】: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 规范名称是唯一的 【参考方案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 我已经稍微扩展了我的要求。你的解决方案对我来说是完美的。你能帮我做些改变吗? ***.com/questions/63541003/…

以上是关于从 Oracle PL/SQL 中的表生成 json 文件的主要内容,如果未能解决你的问题,请参考以下文章

循环遍历 Oracle PL/SQL 中的表

ORACLE PL/SQL 中的表值函数

循环oracle pl/sql中的表名

oracle:使用 PL/sql 过程从另一个模式填充表

pl/SQL 过程从不同表中的值生成一个表中的值

pl/sql 存储过程从日期等于存储过程参数的表中进行选择