26

背景

我需要从 Oracle 获取几千行并将它们转换为 JSON 以在 SlickGrid 中使用。目前我正在获取 PHP 中的行,使用 iconv 将其从 ISO 转换为 UTF-8,并使用 json_encode 导出为 json。整个操作在 DB 端大约需要 1 秒,生成 JSON 需要 5 秒。这是很长的路。

问题

我读过 Oracle 12c 支持 JSON,但我找不到我需要的确切内容。

有没有办法以 json 格式返回标准 sql 查询的结果?

据说我想发出类似这样的查询:

SELECT * from table AS JSON

并收到一个与此类似的有效 json:

[{"col1": "value1", "col2": 2}, {"col1": "valueOfRow2", "col2": 3}]

重要的是我需要为我转义 unicode 序列,因为我在客户端使用 ISO-8859-2 字符集,并且 JSON 必须是 UTF-8 或序列转义。

4

9 回答 9

17

Oracle 12c 版本 12.1.0.2(截至 11.11.2014 的最新版本)添加了 JSON 支持: https ://docs.oracle.com/database/121/NEWFT/chapter12102.htm#BGBGADCC

它从 10 月 17 日开始提供。https://blogs.oracle.com/db/entry/oracle_database_12c_release_1

如果您无法修补/使用该版本,则 Lewis Cunningham 和 Jonas Krogsboell 编写了一个出色的软件包:PL/JSON * http://pljson.sourceforge.net/

这是一个出色的软件包(我在许多数据库安装中都使用过它)。

包含的示例很好,涵盖了大多数场景。

declare 
  ret json;
begin
  ret := json_dyn.executeObject('select * from tab');
  ret.print;
end;
/
于 2014-11-11T09:30:52.300 回答
16

12cR2(在 Oracle 云中可用)本机支持这一点。

SQL> select JSON_ARRAY(EMPLOYEE_ID, FIRST_NAME,LAST_NAME) from HR.EMPLOYEES;

JSON_ARRAY(EMPLOYEE_ID,FIRST_NAME,LAST_NAME)
--------------------------------------------------------------------------------
[100,"Steven","King"]
[101,"Neena","Kochhar"]

或者

SQL> select JSON_OBJECT('ID' is EMPLOYEE_ID , 'FirstName' is FIRST_NAME,'LastName' is LAST_NAME) from HR.EMPLOYEES;

JSON_OBJECT('ID'ISEMPLOYEE_ID,'FIRSTNAME'ISFIRST_NAME,'LASTNAME'ISLAST_NAME)
----------------------------------------------------------------------------
{"ID":100,"FirstName":"Steven","LastName":"King"}
{"ID":101,"FirstName":"Neena","LastName":"Kochhar"}
于 2017-01-05T21:55:12.927 回答
8

12.2 版包含直接从 SQL 查询生成 JSON 文档的新功能。实现目标的最简单方法是使用函数:JSON_OBJECTJSON_ARRAYAGG

create table tab as
    select level col1, 'value '||level col2 from dual connect by level <= 2
/ 

select max (rownum) rn, json_arrayagg (
    json_object (
        key 'col1' value col1,
        key 'col2' value col2
    ) format json returning clob 
) as json_doc
from tab;

结果:

        RN JSON_DOC                                                                        
---------- ---------------------------------------------------------
         2 [{"col1":1,"col2":"value 1"},{"col1":2,"col2":"value 2"}] 

用大量数据进行测试:

select rn, length (json_doc) json_size, json_doc from (
    <query mentoined above here>
    cross join (select dummy from dual connect by level <= 1e5) 
    );

        RN  JSON_SIZE JSON_DOC                                                                        
---------- ---------- ---------------------------------------------------------
    200000    5600001 [{"col1":1,"col2":"value 1"},{"col1":2,"col2":"value 2"},

在慢速测试机器上花了大约 1 秒。创建 5,6M JSON。


在 19c 版本中,函数的语法JSON_OBJECT被简化了。
上面的查询现在看起来像这样:

select json_arrayagg (  
    json_object (*) returning clob   
) as json_doc  
from tab;

实时 SQL上。

于 2019-08-04T12:20:23.827 回答
7

您可以使用 xmltype 将 SQL 的结果转换为 XML 和 JSON。请参阅以下文章,了解自版本 9 起适用于 Oracle 的解决方案。您还可以下载包 itstar_xml_util:

http://stefan-armbruster.com/index.php/12-it/pl-sql/12-oracle-xml-and-json-goodies

emp表的一个简单示例:

declare
  l_sql_string varchar2(2000);
  l_xml        xmltype;
  l_json       xmltype;
begin
  l_sql_string := 'select a.empno, a.ename, a.job from emp a';

  -- Create the XML from SQL
  l_xml := itstar_xml_util.sql2xml(l_sql_string);

  -- Display the XML
  dbms_output.put_line(l_xml.getclobval());

  l_json := itstar_xml_util.xml2json(l_xml);
  -- Display the JSON
  dbms_output.put_line(l_json.getclobval());  
end;

结果如下所示:

{"ROWSET": [
    {
      "EMPNO": 7839,
      "ENAME": "KING",
      "JOB": "PRESIDENT"
    },
    {
      "EMPNO": 7698,
      "ENAME": "BLAKE",
      "JOB": "MANAGER"
    },
[...]
    {
      "EMPNO": 7934,
      "ENAME": "MILLER",
      "JOB": "CLERK"
    }
  ]}
于 2014-11-11T08:40:48.363 回答
3

从 Oracle 19c 开始,为表中的一行构造 JSON 表示的语法得到了简化

例如:要将 的所有行转换hr.employees为单独的 json,请使用

SELECT JSON_OBJECT(*) FROM hr.employees ;

{
"EMPLOYEE_ID" : 100,
"FIRST_NAME" : "Steven",
"LAST_NAME" : "King",
"EMAIL" : "SKING",
"PHONE_NUMBER" : "515.123.4567",
"HIRE_DATE" : "2003-06-17T00:00:00",
"JOB_ID" : "AD_PRES",
"SALARY" : 24000,
"COMMISSION_PCT" : null,
"MANAGER_ID" : null,
"DEPARTMENT_ID" : 90
}                       --row 1
{
"EMPLOYEE_ID" : 101,
"FIRST_NAME" : "Neena",
"LAST_NAME" : "Kochhar",
"EMAIL" : "NKOCHHAR",
"PHONE_NUMBER" : "515.123.4568",
"HIRE_DATE" : "2005-09-21T00:00:00",
"JOB_ID" : "AD_VP",
"SALARY" : 17000,
"COMMISSION_PCT" : null,
"MANAGER_ID" : 100,
"DEPARTMENT_ID" : 90
}                       --row 2
 ...

实时 SQL 示例

于 2019-03-31T17:08:39.983 回答
2

Oracle 12c 对 JSON 的支持是一种存储 JSON 对象、查询它们并从中选择的能力。

您有表格格式,只需要将数据显示为 JSON。所以你可以简单地将行连接成 {'col1': 'rowN1', 'col2': 'rowN2'} 并将其余的放在客户端。或者您可以使用 LISTAGG 来获取整个文档。示例: http ://technology.amis.nl/2011/06/14/creating-json-document-straight-from-sql-query-using-listagg-and-with-clause/

请注意 4000 个字符的 SQL VARCHAR2 限制。

您也可以查看http://database-geek.com/2009/03/25/json-in-and-out-of-oracle-json-data-type/但我不认为,那个 oracle 对象类型会提高你的表现。

另一种方法是使用 XMLType 导出 XML。然后将 XML 转换为 JSON。XMLType 将处理特殊字符,并且 API 相当稳定(您无需为 Oracle 14 重写程序)。

于 2014-05-09T13:20:03.637 回答
2

要添加到 oracle 12.2 中的答案,您可以像这样根据需要创建 json。

SELECT JSON_ARRAY(
JSON_OBJECT (
         KEY 'number' VALUE s.number,
         KEY 'name' VALUE s.sname,
         KEY 'location' VALUE s.loc
          )
       ) AS student_det
FROM   student s;
于 2017-11-03T14:12:11.407 回答
1

试试这个:

:) 生活是快乐的

with data as
  ( select 
    xmlelement(e,regexp_replace('{"name":"'||colname||'"}', '[[:cntrl:]]', ''),',') col1
    from tblname
  )
  select
        rtrim(replace(replace(replace(xmlagg(col1).getclobval(),'&'||'quot;','"'),'<E>',''),'</E>',''),',')
        as very_long_json
  from data;
于 2019-01-21T12:37:49.797 回答
-2

我没有看到 Python 解决方案(以防您需要转储 JSON)。

我为中等大小的提取编写了json-ora-extract(因为数据集必须适合可用内存)。

它使用Python 模块从 Oracle 数据库(任何版本)读取数据并将其转储到wx_Oracle文件中。json*.json

还有一个创建压缩*.gz文件的选项。

于 2017-09-11T20:30:55.697 回答