web-dev-qa-db-ja.com

Oracle 12cでSQLクエリの結果をJSONとして返す

背景

Oracleから数千行をフェッチし、SlickGridで使用するためにJSONに変換する必要があります。現在、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}]

重要なことは、クライアント側でISO-8859-2文字セットを使用し、JSONがUTF-8であるか、シーケンスをエスケープする必要があるため、Unicodeシーケンスをエスケープする必要があることです。

24
SWilk

Oracle 12cバージョン12.1.0.2(2014年11月11日現在の最新バージョン)は、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;
/
17

12cR2(Oracle Cloudで利用可能)はこれをネイティブにサポートします。

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"}
8
mark d drake

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 aus 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"
    }
  ]}
5
PT_STAR

JSONに対するOracle 12cのサポートは、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/

SQL VARCHAR2の4000文字という制限に注意してください。

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用にプログラムを書き換える必要はありません)。

2
vav

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
 ...

LIVE SQLの例

1
Kaushik Nayak

リリース12.2には、SQLクエリから直接JSONドキュメントを生成するための新しい機能が含まれています。目標を達成する最も簡単な方法は、次の関数を使用することです。 JSON_OBJECT および JSON_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

1
0xdb

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;
1
Himanshu sharma

これを試してください:

:)人生は幸せです

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;
0
Shahbaz Ali