22 SQLを使用したJSONデータの生成

SQLを使用すると、データベース内のJSON以外のデータからJSONオブジェクトおよび配列を生成できます。これを行うには、コンストラクタJSONまたはSQL/JSONファンクションjson_objectjson_arrayjson_objectaggおよびjson_arrayaggを使用します。

22.1 JSONにおける生成の概要

JSONデータの生成の概要について説明します(ベスト・プラクティス、SQL/JSON生成関数、単純なJSONコンストラクタ構文、入力SQL値の処理、および生成されるデータ)。

データベースのJSON以外のデータからJSONデータを生成するための最適な方法は、SQLを使用する方法です。標準SQL/JSON関数json_objectjson_arrayjson_objectaggおよびjson_arrayaggは、このために設計されています。生成されるデータがJSON型の場合は、JSONデータ型のコンストラクタ関数JSONを使用することが便利な代替の方法です。

どちらの方法を使用しても、SQL問合せからJSONデータを直接簡単に作成できます。非JSONデータをJSONオブジェクトおよびJSON配列として表すことが可能になります。生成関数またはコンストラクタJSONへの呼出しをネストすると、複雑で階層化されたJSON文書を生成できます。ネストされた副問合せは、1対多関係を表すJSONコレクションを生成できます。Foot 1

非JSONデータからJSONデータを構成するための最適な方法

SQL/JSON生成関数の使用のかわりとなる方法は、エラーが発生しやすかったり、非効率的であることが一般的です。

  • 文字列の連結を使用したJSON文書の生成では、エラーが発生しやすくなります。特に、二重引用符(")などの特殊文字をいつ、どのようにエスケープするかという点について、順守する必要がある複雑なルールが多数あります。これらのルールは、見逃されたり誤って解釈されることが多く、その結果、正しくないJSONデータが生成される可能性が生じます。

  • 非JSONの結果セットをデータベースから読み取り、クライアント側のアプリケーション・コードを使用してJSONデータを生成する方法は、特にネットワーク・オーバーヘッドが原因で非常に効率が悪くなることが一般的です。1対多関係をJSONデータとして表す場合は、必要な非JSONデータをすべて収集するために、複数のSELECT操作が必要になることが多くなります。生成する文書で複数のレベルの1対多関係が示される場合は、この方法では必要なコストが増えることが考えられます。

SQL/JSON生成関数およびコンストラクタJSONでは、このような問題が発生しません。非JSONデータベース・データからJSONデータを構成するジョブ向けに設計されています。

  • これらの関数では、常に整形式のJSON文書が構成されます。

  • 関数でSQL副問合せを使用すると、1つのSQL文を使用してJSON文書一式を生成できるため、生成処理を最適化できます。

  • クライアントに戻されるのは、生成された文書だけなので、ネットワーク・オーバーヘッドは最小化されます。生成される文書当たり、多くても1往復で済みます。

SQL/JSONの生成関数

  • ファンクションjson_objectおよびjson_arrayは、それぞれJSONオブジェクトまたは配列を構成します。最も単純なケースでは、json_objectは引数としてSQL名前/値ペアを受け取り、json_arrayは引数としてSQL値を受け取ります。

  • 関数json_objectaggおよびjson_arrayaggは、集計のSQLファンクションです。これらの関数は、グループ化されたSQL問合せの行に格納された情報を、それぞれ、JSONオブジェクトと配列に変換します。引数の評価によって、オブジェクト・メンバーと配列要素の数が決まります。つまり、結果のサイズは現在の問合せ対象データを反映します。

    json_objectaggおよびjson_arrayaggの場合、オブジェクト・メンバーと配列要素の順序は、指定されません。json_arrayaggの場合、json_arrayaggの呼出し内でORDER BY句を使用すると、配列要素の順序を制御できます。

SQL/JSON生成関数によって戻される結果

デフォルトでは、生成されたJSONデータは生成関数からSQL VARCHAR2(4000)値として戻されます。オプションのRETURNING句を使用して、異なるVARCHAR2サイズを指定するか、かわりにJSONCLOBまたはBLOBの戻り値を指定できます。BLOBが戻り型の場合、キャラクタ・セットはAL32UTF8です。

戻り型がJSONである場合を除き、入力SQL値から生成されるJSON値はテキストのJSONにシリアライズされます。このシリアライズは、Oracle SQLファンクションjson_serializeと同じ効果があります。

SQL/JSON生成関数の入力値の処理

SQL/JSON生成関数は入力としてSQLの値を受け取り、返されるJSONオブジェクトまたは配列内にJSON値を生成します。出力に使用されるJSON値が入力値からどのように生成されるかは、それらのSQLデータ型によって異なります。

SQL/JSON生成関数のオプションの動作

オプションとして、SQL NULLを処理する句、RETURNING句およびキーワードSTRICTおよびWITH UNIQUE KEYSを指定できます。

  • NULLを処理する句: 入力評価の結果のSQL NULL値をどのように扱うかを決定します。

    • NULL ON NULL: 入力のSQL NULL値が、出力のJSON nullに変換されます。これは、json_objectjson_objectaggのデフォルト動作です。

    • ABSENT ON NULL: 入力のSQL NULL値の結果、対応する出力がない状態になります。これは、json_arrayjson_arrayaggのデフォルト動作です。

  • RETURNING句: 関数の戻り値に使用されるSQLデータ型です。戻り型は、JSONデータをサポートする任意のSQL型にすることができます(JSONVARCHAR2CLOBまたはBLOB)。デフォルトの戻り型(RETURNING句なし)はVARCHAR2(4000)です。

  • STRICTキーワード: 指定すると、戻されるJSONデータが整形式になっているかチェックされます。STRICTを指定して戻されたデータが整形式でない場合には、エラーが発生します。

    注意:

    通常、JSONデータ型のデータの生成時にSTRICTを指定する必要はなく、これを行うと若干のパフォーマンス・ペナルティが生じます。

    入力データおよび返されるデータの両方がJSON型の場合、STRICTを指定しないと、その入力は返されるデータにそのまま使用されます。厳密な整形式としてチェックされません。

    (1)入力データもJSON型であり、(2)それが完全に厳密ではない可能性がある場合、JSON型のデータを返すときにSTRICTを使用できます。たとえば、クライアント・アプリケーションで入力データが作成され、各JSON文字列が有効なUTF-8のバイト・シーケンスで表されていることが保証されない場合などです。

  • WITH UNIQUE KEYSキーワード(json_objectおよびjson_objectaggにのみ使用可能) — 存在する場合、返されるJSONオブジェクトがチェックされ、重複するフィールド名がないことが確認されます。重複がある場合は、エラーが発生します。

    指定しない場合(またはWITHOUT UNIQUE KEYSが指定されている場合)、一意のフィールドのチェックは実行されません。その場合は次のようになります。

    • 戻りデータ型がJSONの場合は、重複する一連のフィールドのうちの1つのみが使用され、どのフィールドが使用されるかは定義されていません。

    • 戻りデータ型がJSONではない場合は、重複するフィールドを含むすべてのフィールドが使用されます。

JSONデータ型コンストラクタ

JSONデータ型のデータの生成時にjson_objectおよびjson_arrayを使用するかわりに、コンストラクタJSONを特別な構文とともに使用できます。(コンストラクタJSONおよびJSON型を使用できるのは、データベース初期化パラメータcompatibleが少なくとも20の場合のみです。そうでない場合は、エラーが発生します。)

動作の違いは、コンストラクタを使用したときの戻りデータ型は、常にJSONであるということのみです(コンストラクタにはRETURNING句はありません)。

json_objectまたはjson_arrayの代替構文として使用する場合は、オブジェクトと配列の生成時に、通常のカッコ(())ではなく、中カッコ({})と大カッコ([])をそれぞれ使用して、コンストラクタJSONを直接実行します。

  • JSON { … }JSON(json_object( … ))と同じ効果があり、後者はjson_object( … RETURNING JSON)と同じ効果があります。

  • JSON [ … ]JSON(json_array( … ))と同じ効果があり、後者はjson_array( … RETURNING JSON)と同じ効果があります。

json_objectおよびjson_arrayRETURNING JSONとともに使用される場合のこれらのファンクションの動作と構文のすべての選択肢は、特別な構文を持つコンストラクタJSONを使用する場合にも利用できます。たとえば、例22-2例22-3例22-4例22-5および例22-6を参照してください。

JSON {…}およびJSON […]は、json_objectおよびjson_arrayのみの代替構文であり、集計生成関数json_objectaggおよびjson_arrayaggには使用できません。ただし、json_objectaggまたはjson_arrayaggへの明示的な呼出しの結果に対して、(特別な構文なしで)コンストラクタJSONを使用することもできます。たとえば、この2つの問合せは等価です。

SELECT JSON(json_objectagg(department_name VALUE department_id))
  FROM departments;

SELECT json_objectagg(department_name VALUE department_id
                      RETURNING JSON)
  FROM departments;

関連項目:

22.2 SQL/JSON生成関数の入力値の処理

SQL/JSON生成関数は、入力としてSQL値を受け取り、JSONオブジェクトまたは配列を返します。入力値を使用して、JSONオブジェクトのフィールド値のペアまたはJSON配列の要素を生成します。入力値を使用する方法は、SQLデータ型によって異なります。

返されるJSONオブジェクトまたは配列は、JSONデータをサポートするSQLデータ型です(JSONVARCHAR2CLOBまたはBLOB)。デフォルトの戻り型はVARCHAR2(4000)です。すべての場合に、戻り値には整形式のJSONデータが含まれていることをデータベースが認識します。

JSONデータ型以外の場合、入力の後にキーワードFORMAT JSONを指定できます。このキーワードは、値がすでにJSONデータを表しているとみなされるように宣言するため(ユーザーがそれを保証します)、JSONデータとして解釈(解析)されます。たとえば、入力が'{}'の場合に、JSON文字列"{}"ではなく、空のJSONオブジェクト{}を生成する場合があります。例22-1では、FORMAT JSONを使用して、入力SQL文字列"true"からJSONのブール値trueを生成しています。

同様に、入力の型がJSONでない場合、SQLファンクションtreatにキーワードAS JSONを指定して適用できます。効果は、FORMAT JSONを使用した場合と同じです。

入力データがJSON型の場合は、そのまま使用されます。これには、JSON型コンストラクタが使用される場合も含まれます。(この場合、FORMAT JSONまたはtreatAS JSONを使用しないでください。使用するとエラーが発生します。)

入力がJSONではなくFORMAT JSONまたはtreatAS JSONを使用しない場合でも、Oracleは結果がJSONデータであることを認識します。そのような場合、FORMAT JSONまたはtreatAS JSONを使用することは必須ではなく、任意です。これは、たとえば、入力データがファンクションjson_queryまたはJSON生成関数のいずれかを使用した結果である場合です。

何らかの方法で入力がJSONデータと認識されている場合、その入力は基本的にそのまま使用されて、結果が構成されます(処理は不要です)。これは入力がJSONスカラー、オブジェクトまたは配列のいずれを表すかにかかわらず適用されます。

入力がJSONデータであると認識されない場合は、次のようなJSON値が生成されます(他のSQL値の場合はエラーが発生します)。

  • ユーザー定義のSQLオブジェクト型のインスタンスの場合は、フィールド名がオブジェクト属性名から取得され、フィールド値が(JSON生成が再帰的に適用される)オブジェクト属性値から取得されるJSONオブジェクトが生成されます。

  • SQLコレクション型のインスタンスの場合は、(JSON生成が再帰的に適用される)コレクション要素の値から要素の値が取得されるJSON配列が生成されます。

  • VARCHAR2CLOBまたはNVARCHAR値は、二重引用符(")で囲まれ、JSON標準のJSON文字列に準拠するように、必要に応じて文字がエスケープされます。たとえば、SQL入力'{}'の場合は、JSON文字列"{}"が生成されます。

  • 数値の場合は、JSON数値が生成されます。

    compatibleが少なくとも20であれば、入力がNUMBERの場合はJSONのnumber、BINARY_DOUBLEの場合はJSONのdouble値、およびBINARY_FLOATの場合はJSONのfloat値が生成されます。

    データベース初期化パラメータcompatible20より低い場合、数値入力型(NUMBERBINARY_DOUBLEまたはBINARY_FLOAT)に関係なく、値はJSONのnumberになります。

    正の無限大および負の無限大の数値、および数値演算の未定義の結果である値(非数値、つまりNaN)は、JSON数値として表すことができません。これらはかわりにJSON文字列を生成します(それぞれ"Inf""-Inf"および"Nan")。

  • RAWまたはBLOB値の場合は、二重引用符(")で囲まれた16進のJSON文字列が生成されます。

  • 時間に関連した値(DATETIMESTAMPTIMESTAMP WITH TIME ZONETIMESTAMP WITH LOCAL TIME ZONEINTERVAL YEAR TO MONTHまたはINTERVAL DAY TO SECOND)の場合は、サポートされているISO 8601形式が生成され、その結果はJSON文字列として二重引用符(")で囲まれます。

  • BOOLEAN PL/SQL値のTRUEまたはFALSEの場合は、JSONのtrueまたはfalseがそれぞれ生成されます。

  • SQLのNULL値の場合は、NULLデータ型に関係なく、JSONのnullが生成されます。

注意:

CLOBおよびBLOBデータ型の入力の場合は、空のインスタンスがSQLのNULLと区別されます。空のJSON文字列("")が生成されます。ただし、データ型VARCHAR2NVARCHAR2およびRAWの入力の場合、Oracle SQLでは空の値(長さがゼロ)をNULLとして扱うため、そのような値がJSON文字列に生成されると想定しないでください

例22-1 入力値のJSONとしての宣言

この例では、JSONのブール値trueおよびfalseが使用されるようにするために、FORMAT JSONをSQL文字列値'true'および'false'に対して指定します。FORMAT JSONを指定しないと、フィールドhasCommissionの値はJSON文字列"true"および"false"となり、JSONブールtrueおよびfalseにはなりません。

SELECT json_object('name'          VALUE first_name || ' ' || last_name,
                   'hasCommission' VALUE
                     CASE WHEN commission_pct IS NULL THEN 'false'
                                                      ELSE 'true'
                     END FORMAT JSON)
  FROM employees WHERE first_name LIKE 'W%';

JSON_OBJECT('NAME'ISFIRST_NAME||''||LAST_NAME,'
-----------------------------------------------
{"name":"William Gietz","hasCommission":false}
{"name":"William Smith","hasCommission":true}
{"name":"Winston Taylor","hasCommission":false}

22.3 SQL/JSONファンクションJSON_OBJECT

SQL/JSONファンクションjson_objectは、引数のSQL式を評価した結果からJSONオブジェクトを構成します。

任意の数の引数を指定でき、各引数は次のいずれかにできます。

  • 明示的なフィールド名/値ペア。例: answer : 42

  • 表名または別名、あるいはビュー名の後にドットとアスタリスクのワイルドカード(.*)。例: t1.*。(名前や別名には、myschema.t1.*のように、データベース・スキーマ名の接頭辞を付けることができます。)

  • リレーショナル列名。その前に表名または別名、あるいはビュー名の後にドット(.)が続く場合があります。例: t1.address

あるいは、アスタリスク・ワイルドカード(*)またはユーザー定義のSQLオブジェクト型の単一インスタンスである単一の引数を受け入れます。

アスタリスク・ワイルドカードの使用方法を説明するもう1つの方法は、SQL SELECT一覧でワイルドカードに許可されているものに従っているということです。

名前/値ペア引数は、生成されたJSONオブジェクトのオブジェクト・メンバーを指定します(値式がSQL NULLに評価される場合、およびABSENT ON NULL句が適用される場合を除く)。名前と値はSQL式です。名前式は、SQL文字列に評価される必要があります。式は、JSONデータ型のSQL値、またはJSON値として表すことができるSQL値に評価される必要があります。名前式と値式は、キーワードVALUEまたはコロン(:)で区切られます。

注意:

一部のクライアント・ドライバは、問合せをデータベースに送信する前に、問合せテキストのスキャンとバインド変数の特定を試みる場合があります。その場合、バインド変数を導入するときに、json_object内の名前/値セパレータであるコロンが誤解釈されることがあります。この問題を回避するために、キーワードVALUEをセパレータとして使用('Name' VALUE Diderot)するか、単にペアの値部分をカッコで囲みます('Name':(Diderot))。

列名を引数として使用する場合は、指定されたデータ行について、列名引数で指定されたオブジェクト・メンバーにフィールド名としての列名とフィールド値としての列値が含まれます。引用符で囲まれているかどうかに関係なく、指定する列名は大/小文字を区別して解釈されます。たとえば、Emailを列名引数として使用する場合、EMAIL列のデータは、フィールド名Emailを持つオブジェクト・メンバーの生成に使用されます。

アスタリスク(*)ワイルドカードをショートカットとして使用し、特定の表またはビューの列をすべて明示的に指定してオブジェクト・メンバーを作成できます。結果のオブジェクト・フィールド名は、大文字の列名です。ワイルドカードは、表、ビューまたは表の別名とともに使用できます。

個々のJSONオブジェクト・メンバーの定義に使用されるSQL式を渡すかわりに、ユーザー定義のSQLオブジェクト型の単一インスタンスを渡すことができます。これにより、フィールド名がオブジェクト属性名から取得され、フィールド値が(JSON生成が再帰的に適用される)オブジェクト属性値から取得されるJSONオブジェクトが生成されます。

SQL/JSON条件is jsonと同様に、キーワードSTRICTおよびWITH UNIQUE KEYSはファンクションjson_objectおよびjson_objectaggとともに使用できます。それぞれの動作はis jsonと同じです。

例22-2 JSON_OBJECTでの名前/値ペアの使用

この例では、表hr.employees (標準のデータベース・スキーマHRから)の従業員のうち、給与が15000を超える従業員それぞれのJSONオブジェクトが構成されます。

明示的な名前/値のペアを渡してJSONオブジェクト・メンバーを指定します。JSONオブジェクトには、フィールドcontactInfoの値として、フィールドmailphoneのオブジェクトが含められています。

json_objectの戻り値はJSONデータになるため、フィールドcontactInfoの入力形式に対してFORMAT JSONが自動的に推定されており、明示的にFORMAT JSONを使用するは必要ありません。

ここではRETURNING JSONを使用することで、デフォルトの戻り型VARCHAR2(4000)ではなく、JSONデータがJSONデータ型として返されるように指定しています。

SELECT json_object('id'          : employee_id,
                   'name'        : first_name || ' ' || last_name,
                   'hireDate'    : hire_date,
                   'pay'         : salary,
                   'contactInfo' : json_object('mail'  : email,
                                               'phone' : phone_number
                                               FORMAT JSON)
                   RETURNING JSON) 
  FROM hr.employees
  WHERE salary > 15000;

-- The query returns rows such as this (pretty-printed here for clarity):

{"id"          : 101,
 "name"        : "Neena Kochhar",
 "hireDate"    : "21-SEP-05",
 "pay"         : 17000,
 "contactInfo" : {"mail"  : "NKOCHHAR",
                  "phone" : "515.123.4568"}}

JSONデータの戻り型はJSONであるため、これは同じ問合せの代替の構文です。

SELECT JSON { 'id'          : employee_id,
              'name'        : first_name || ' ' || last_name,
              'hireDate'    : hire_date,
              'pay'         : salary,
              'contactInfo' : JSON { 'mail'  : email,
                                     'phone' : phone_number } } 
  FROM hr.employees
  WHERE salary > 15000;

例22-3 JSON_OBJECTでの列名の使用

この例では、employee_id101である従業員のJSONオブジェクトを構成します。生成されるフィールドには列の名前が付けられ、大/小文字が区別されます。

SELECT json_object(last_name,
                   hire_date,
                   salary,
                   'contactInfo' : json_object(email, phone_number)
                   RETURNING JSON)
  FROM hr.employees
  WHERE employee_id = 101;

-- The query returns rows such as this (pretty-printed here for clarity):

{"last_name"   : "Neena Kochhar",
 "hire-date"   : "21-SEP-05",
 "salary"      : 17000,
 "contactInfo" : {"email"        : "NKOCHHAR",
                  "phone_number" : "515.123.4568"}}

JSONデータの戻り型はJSONであるため、これは同じ問合せの代替の構文です。

SELECT JSON { last_name,
              hire_date,
              salary,
              'contactInfo' : JSON { email, phone_number } }
  FROM hr.employees
  WHERE employee_id = 101;

例22-4 JSON_OBJECTでのワイルドカード(*)の使用

この例では、給与が15000を超える従業員ごとにJSONオブジェクトを構成します。従業員表の各列は、そのフィールド名が(大文字)列名である1つのオブジェクト・メンバーの構成に使用されます。SQL NULL値によってJSONフィールド値がnullになることに注意してください。

SELECT json_object(* RETURNING JSON)
  FROM hr.employees
  WHERE salary > 15000;

-- The query returns rows such as this (pretty-printed here for clarity):

JSON_OBJECT(*)
--------------
{"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}

{"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}

{"EMPLOYEE_ID":102,
 "FIRST_NAME":"Lex",
 "LAST_NAME":"De Haan",
 "EMAIL":"LDEHAAN",
 "PHONE_NUMBER":"515.123.4569",
 "HIRE_DATE":"2001-01-13T00:00:00",
 "JOB_ID":"AD_VP",
 "SALARY":17000,
 "COMMISSION_PCT":null,
 "MANAGER_ID":100,
 "DEPARTMENT_ID":90}

JSONデータの戻り型はJSONであるため、これは同じ問合せの代替の構文です。

SELECT JSON { * }
  FROM hr.employees
  WHERE salary > 15000;

例22-5 ABSENT ON NULLを指定したJSON_OBJECTの使用

この例では、標準のデータベース・スキーマHRの表hr.locationsに対する問合せを実行して、フィールドcityprovinceが含まれるJSONオブジェクトを作成します。

json_objectに対するNULL処理のデフォルト動作は、NULL ON NULLです。

JSON値nullが含まれるフィールドが作成されないようにするために、この例ではABSENT ON NULLを使用します。列cityの値が'Singapore'のときに列state_provinceがSQL値NULLになるということは、その場所に対してprovinceフィールドが作成されていないことを意味します。

SELECT JSON_OBJECT('city'     VALUE city,
                   'province' : state_province ABSENT ON NULL) 
  FROM hr.locations
  WHERE city LIKE 'S%';

JSON_OBJECT('CITY'ISCITY,'PROVINCE'ISSTATE_PROVINCEABSENTONNULL)
----------------------------------------------------------------
{"city":"Southlake","province":"Texas"}
{"city":"South San Francisco","province":"California"}
{"city":"South Brunswick","province":"New Jersey"}
{"city":"Seattle","province":"Washington"}
{"city":"Sydney","province":"New South Wales"}
{"city":"Singapore"}
{"city":"Stretford","province":"Manchester"}
{"city":"Sao Paulo","province":"Sao Paulo"}

この例にはRETURNING句がないため、JSONデータはデフォルトでVARCHAR2(4000)として返されます。RETURNING JSONを使用した場合は、問合せにこの代替の構文を使用できます。

SELECT JSON {'city'     VALUE city,
                   'province' : state_province ABSENT ON NULL} 
  FROM hr.locations
  WHERE city LIKE 'S%';

例22-6 JSON_OBJECTでのユーザー定義のオブジェクト型インスタンスの使用

この例では、オブジェクト型がshipping_tの列shippingを使用して表po_shipを作成します。(SQL/JSONファンクションjson_valueを使用してJSONデータからshipping_tインスタンスを構成します。例17-3を参照。)

次に、json_objectを使用して、po_ship.shipping列にあるSQLオブジェクト型インスタンスからJSONオブジェクトを生成し、JSONデータ型のインスタンスとして返します。

(ここでは、わかりやすいように、問合せの出力をフォーマット出力しています。)

CREATE TABLE po_ship
  AS SELECT json_value(po_document, '$.ShippingInstructions'
                       RETURNING shipping_t)
  shipping
  FROM j_purchaseorder;

DESCRIBE po_ship;

Name      Null?   Type
--------- ------- ----------
SHIPPING          SHIPPING_T

SELECT json_object(shipping RETURNING JSON)
  FROM po_ship;

JSON_OBJECT(SHIPPING)
---------------------
{"NAME":"Alexis Bull",
 "ADDRESS":{"STREET":"200 Sporting Green",
            "CITY":"South San Francisco"}}
{"NAME":"Sarah Bell",
 "ADDRESS":{"STREET":"200 Sporting Green",
            "CITY":"South San Francisco"}}

json_objectの戻り型はJSONであるため、これは同じ問合せの代替の構文です。


SELECT JSON {shipping} FROM po_ship;

関連項目:

22.4 SQL/JSONファンクションJSON_ARRAY

SQL/JSONファンクションjson_arrayは、引数のSQL式を評価した結果からJSON配列を構成します。

最も単純なケースでは、json_arrayに指定する評価済引数は、JSON配列要素としてJSON値が生成されるSQL値です。結果の配列には、指定する引数ごとに要素が含められます(引数式がSQL NULLに評価される場合と、ABSENT ON NULL句が適用される場合を除く)。配列要素の順序は、引数の順序と同じです。

json_arrayの引数として使用できるSQL値には、SQLスカラー、コレクション・インスタンス、ユーザー定義のオブジェクト型インスタンスなど、いくつかの種類があります。

例22-7 JSON_ARRAYを使用したJSON配列の構成

この例では、データベース表hr.jobs (標準のデータベース・スキーマHRから)に含まれる各従業員の仕事のJSONオブジェクトが構成されます。オブジェクトのフィールドは、役職と給与の範囲です。給与の範囲(フィールドsalaryRange)は、仕事に対する最小給与と最大給与の2つの数値の配列です。これらの値は、SQL列min_salaryおよびmax_salaryから取得されます。

ここではRETURNING JSONを使用することで、デフォルトの戻り型VARCHAR2(4000)ではなく、JSONデータがJSONデータ型として返されるように指定しています。

SELECT json_object('title'       VALUE job_title, 
                   'salaryRange' VALUE json_array(min_salary, max_salary)
                   RETURNING JSON)
  FROM jobs;

JSON_OBJECT('TITLE'ISJOB_TITLE,'SALARYRANGE'ISJSON_ARRAY(MIN_SALARY,
--------------------------------------------------------------------
{"title":"President","salaryRange":[20080,40000]}
{"title":"Administration Vice President","salaryRange":[15000,30000]}
{"title":"Administration Assistant","salaryRange":[3000,6000]}
{"title":"Finance Manager","salaryRange":[8200,16000]}
{"title":"Accountant","salaryRange":[4200,9000]}
{"title":"Accounting Manager","salaryRange":[8200,16000]}
{"title":"Public Accountant","salaryRange":[4200,9000]}
{"title":"Sales Manager","salaryRange":[10000,20080]}
{"title":"Sales Representative","salaryRange":[6000,12008]}
{"title":"Purchasing Manager","salaryRange":[8000,15000]}
{"title":"Purchasing Clerk","salaryRange":[2500,5500]}
{"title":"Stock Manager","salaryRange":[5500,8500]}
{"title":"Stock Clerk","salaryRange":[2008,5000]}
{"title":"Shipping Clerk","salaryRange":[2500,5500]}
{"title":"Programmer","salaryRange":[4000,10000]}
{"title":"Marketing Manager","salaryRange":[9000,15000]}
{"title":"Marketing Representative","salaryRange":[4000,9000]}
{"title":"Human Resources Representative","salaryRange":[4000,9000]}
{"title":"Public Relations Representative","salaryRange":[4500,10500]}

JSONデータの戻り型はJSONであるため、これは同じ問合せの代替の構文です。


SELECT JSON { 'title'       VALUE job_title, 
              'salaryRange' VALUE JSON [ min_salary, max_salary ] }
  FROM jobs;

関連項目:

SQL/JSONファンクションjson_arrayおよび同等のJSONコンストラクタ([…])の構文の詳細は、Oracle Database SQL言語リファレンス

22.5 SQL/JSONファンクションJSON_OBJECTAGG

SQL/JSONファンクションjson_objectaggは、グループ化されたSQL問合せの複数行の情報をオブジェクト・メンバーとして集計して、JSONオブジェクトを構成します。

結果のオブジェクトに含まれるメンバーの数が引数の数を直接反映するSQL/JSONファンクションjson_objectの場合とは異なり、json_objectaggでは、結果のオブジェクトのサイズは現在の問合せ対象データを反映します。このように、問合せ対象のデータによって結果のサイズが変わる可能性があります。

例22-8 JSON_OBJECTAGGを使用したJSONオブジェクトの構成

この例では、表hr.departments(標準のデータベース・スキーマHR)から単一のJSONオブジェクトを構成します。その際、列department_nameから取得したフィールド名と列department_idから取得したフィールド値が使用されます。

SQL/JSON条件is jsonと同様に、キーワードSTRICTおよびWITH UNIQUE KEYSはファンクションjson_objectおよびjson_objectaggとともに使用できます。それぞれの動作はis jsonと同じです。

SELECT json_objectagg(department_name VALUE department_id)
  FROM departments;

-- The returned object is pretty-printed here for clarity.
-- The order of the object members is arbitrary.

JSON_OBJECTAGG(DEPARTMENT_NAMEISDEPARTMENT_ID)
----------------------------------------------
{"Administration":        10,
 "Marketing":             20,
 "Purchasing":            30,
 "Human Resources":       40,
 "Shipping":              50,
 "IT":                    60,
 "Public Relations":      70,
 "Sales":                 80,
 "Executive":             90,
 "Finance":              100,
 "Accounting":           110,
 "Treasury":             120,
 "Corporate Tax":        130,
 "Control And Credit":   140,
 "Shareholder Services": 150,
 "Benefits":             160,
 "Manufacturing":        170,
 "Construction":         180,
 "Contracting":          190,
 "Operations":           200,
 "IT Support":           210,
 "NOC":                  220,
 "IT Helpdesk":          230,
 "Government Sales":     240,
 "Retail Sales":         250,
 "Recruiting":           260,
 "Payroll":              270}

関連項目:

SQL/JSONファンクションjson_objectaggの詳細は、Oracle Database SQL言語リファレンスを参照してください。

22.6 SQL/JSONファンクションJSON_ARRAYAGG

SQL/JSONファンクションjson_arrayaggは、グループ化されたSQL問合せの複数行の情報を配列要素として集計して、JSON配列を構成します。配列要素の順序は、デフォルトでは、問合せ結果の順序に反映されますが、ORDER BY句を使用すると、配列要素の順序を指定できます。

結果の配列に含まれる要素の数が引数の数を直接反映するSQL/JSONファンクションjson_arrayの場合とは異なり、json_arrayaggでは、結果の配列のサイズは現在の問合せ対象データを反映します。このように、問合せ対象のデータによって結果のサイズが変わる可能性があります。

例22-9 JSON_ARRAYAGGを使用したJSON配列の構成

この例では、表hr.employees(標準のデータベース・スキーマHRから)の従業員のうち、6名以上の従業員を管理するマネージャである従業員それぞれのJSONオブジェクトが構成されます。オブジェクトには、マネージャID番号、マネージャ名、そのマネージャに報告する従業員の数、それらの従業員のID番号用のフィールドがあります。

配列内に含まれる従業員のID番号の順序は、json_arrayaggORDER BY句で決定されます。ORDER BYのデフォルトの方向はASC (昇順)です。配列要素(数値)は、数値順の昇順に並べられます。

SELECT json_object('id'         VALUE mgr.employee_id, 
                   'manager'    VALUE (mgr.first_name || ' '|| mgr.last_name),
                   'numReports' VALUE count(rpt.employee_id),
                   'reports'    VALUE json_arrayagg(rpt.employee_id
                                                    ORDER BY rpt.employee_id))
  FROM  employees mgr, employees rpt
  WHERE mgr.employee_id = rpt.manager_id
  GROUP BY mgr.employee_id, mgr.last_name, mgr.first_name
  HAVING count(rpt.employee_id) > 6;

-- The returned object is pretty-printed here for clarity.

JSON_OBJECT('ID'ISMGR.EMPLOYEE_ID,'MANAGER'VALUE(MGR.FIRST_NAME||''||MGR.LAST_NAME)
-----------------------------------------------------------------------------------
{"id":         100,
 "manager":    "Steven King",
 "numReports": 14,
 "reports":    [101,102,114,120,121,122,123,124,145,146,147,148,149,201]}

{"id":         120,
 "manager":    "Matthew Weiss",
 "numReports": 8,
 "reports":    [125,126,127,128,180,181,182,183]}

{"id":         121,
 "manager":    "Adam Fripp",
 "numReports": 8,
 "reports":    [129,130,131,132,184,185,186,187]}

{"id":         122,
 "manager":    "Payam Kaufling",
 "numReports": 8,
 "reports":    [133,134,135,136,188,189,190,191]}

{"id":         123,
 "manager":    "Shanta Vollman",
 "numReports": 8,
 "reports":    [137,138,139,140,192,193,194,195]}

{"id":         124,
 "manager":    "Kevin Mourgos",
 "numReports": 8,
 "reports":    [141,142,143,144,196,197,198,199]}

関連項目:

SQL/JSONファンクションjson_arrayaggの詳細は、Oracle Database SQL言語リファレンスを参照してください。



脚注の凡例

脚注1: JSONデータでのSQL/JSON生成関数の動作は、XMLデータのSQL/XML生成関数の動作と似ています。