プライマリ・コンテンツに移動
Oracle® XML DB開発者ガイド
12cリリース1 (12.1)
B71282-04
目次へ移動
目次
索引へ移動
索引

前
次

39 Oracle DatabaseのJSON

Oracle Databaseは、トランザクション、索引付け、宣言的問合せおよびビューを含むリレーショナル・データベースの機能を使用してJavaScript Object Notation (JSON)データをネイティブにサポートしています。

39.1 JSONの概要

JavaScript Object Notation (JSON)は、標準ECMA-404 (JSONデータ交換フォーマット)およびECMA-262 (ECMAScript言語仕様、第3版)で定義されています。ECMAScriptのJavaScript言語は、WebブラウザおよびWebサーバーで広く使用されている汎用プログラミング言語です。

JSONは、JavaScriptのオブジェクト・リテラル表記法のサブセットであるとも言えます。脚注1JSONは、JavaScriptのオブジェクト・リテラルを表すために使用できるため、一般的にデータ交換言語として機能します。この点において、XMLとよく似ています。

JSONは、JavaScript表記法(のサブセットとも言える表記法)であるため、多くの場合、解析やシリアライズを行う必要なくJavaScriptプログラムで使用できます。これは、JavaScriptのオブジェクト・リテラル、配列およびスカラー・データを表すテキスト・ベースの方法です。

JSONは、JavaScriptのコンテキストで定義されているため、実際には言語に依存しないデータ・フォーマットです。JSONデータは様々なプログラミング言語で解析および生成できます。

JSONは、人間にとっては読み書きが比較的簡単であり、ソフトウェアにとっては解析および生成が簡単です。多くの場合、構造化されたデータをシリアライズし、通常はサーバーとWebアプリケーション間でネットワークを介して交換するために使用されます。

関連項目:

39.1.1 JSON構文およびJSON構文が表すデータの概要

JSON (およびJavaScript)の値、スカラー、オブジェクトおよび配列について説明します。

JSON value は、object、array、number、string、、、またはnullのいずれかです。オブジェクトおよび配列を除くすべての値はスカラーです。

注意:

JSON値のnullは、SQLに関するかぎり、1つのです。これは、SQLで値の欠如(存在しないデータ、不明なデータまたは適用できないデータ)を表すNULLとは異なります。特に、SQL条件のIS NULL条件は、JSONのnull値に対してfalseを戻し、SQL条件のIS NOT NULLはtrueを戻します。

JavaScriptオブジェクトは、0個以上のプロパティ名および関連するJSON値のペアの連想配列またはディクショナリです。脚注2 JSONオブジェクトは、JavaScriptのオブジェクト・リテラルです。脚注3 これは、中カッコ({})で囲まれたプロパティ・リストとして作成されますが、この場合、名前と値のペアはカンマ(,)で区切られ、各ペアの名前と値はコロン(:)で区切られます。

JSONでは、各プロパティ名および各文字列値は、二重引用符(")で囲む必要があります。JavaScript表記法では、オブジェクト・リテラルで使用されるプロパティ名は、二重引用符で囲むことができますが、必須ではありません。これはまた、一重引用符(')で囲むこともできます。

こうした違いの結果、実際には、引用符で囲まれていないプロパティ名か一重引用符で囲まれたプロパティ名を使用して表されたデータが、JSONで表されているように緩やかに参照される場合があり、Oracle Database実装を含むJSON実装では、引用符で囲まれていないプロパティ名も、一重引用符で囲まれたプロパティ名も使用できる柔軟な構文がサポートされます。

JSONの文字列は、バックスラッシュ(\)によるエスケープを使用したUnicode文字で構成されています。JSONの数値(数字)は10進数表記法で表され、符号が付いている場合や10進数指数が含まれる場合があります。

オブジェクト・プロパティは、多くの場合フィールドと呼ばれます。オブジェクト・プロパティの名前と値のペアは、オブジェクト・メンバーと呼ばれる場合があります。オブジェクト・メンバー間の順序は重要ではありません。

注意:

  • JSONフィールド名は("" )にできます。脚注 4

  • 特定のJSONオブジェクト内のフィールド名は、それぞれが一意である必要はありません。同じフィールド名を繰り返すことができます。Oracle Databaseで採用されているJSONパスの評価では常に、特定のフィールド名を持つオブジェクト・メンバーの1つのみが使用されます。同じ名前を持つ他のメンバーは無視されます。このような複数のメンバーのうちどれが使用されるかは指定されていません。

    "JSONオブジェクトの一意フィールドと重複フィールドを参照してください。

JavaScript配列には、0個以上の要素があります。JSONでは、配列は配列の要素を囲む大カッコ([])によって表され、これらの要素はカンマ(,)によって区切られ、それぞれがオブジェクト、配列またはスカラー値です。配列要素の順序は重要ではありません。

例39-1は、発注書を表すJSONオブジェクトを示しており、最上位のフィールド名はPONumberReferenceRequestorUserCostcenterShippingInstructionSpecial InstructionsAllowPartialShipmentおよびLineItemsです。

  • ほとんどのフィールドには文字列値があります。たとえば、フィールドUserには値"ABULL"があります。

  • フィールドPONumberおよびzipCodeにはそれぞれ数値1600および99236があります。

  • フィールドShipping Instructionsには値としてオブジェクトがあります。このオブジェクトには、フィールドnameAddressおよびPhoneを持つ3つのメンバーがあります。フィールドnameには文字列値("Alexis Bull")があります。フィールドAddressおよびPhoneにはそれぞれオブジェクト値があります。

  • フィールドAddressの値は、フィールドstreetcitystatezipCodeおよびcountryを持つオブジェクトです。フィールドzipCodeには数値があります。他のフィールドには文字列値があります。

  • フィールドPhoneには値として配列があります。この配列には2つの要素があり、それぞれがオブジェクト・リテラルを表します。これらの各オブジェクトには、フィールドtypeおよびnumberの2つのメンバーとそれらの値があります。

  • フィールドSpecial Instructionsにはnull値があります。

  • フィールドAllowPartialShipmentにはブール値trueがあります。

  • フィールドLineItemsには値として配列があります。この配列には2つの要素があり、それぞれがオブジェクトを表します。これらの各オブジェクトには、フィールドItemNumberPartおよびQuantityを持つ3つのメンバーがあります。

  • フィールドItemNumberおよびQuantityには数値があります。フィールドPartには値として、フィールドDescriptionUnitPriceおよびUPCCodeを持つオブジェクトがあります。フィールドDescriptionには文字列値があります。フィールドUnitPriceおよびUPCCodeには数値があります。

例39-1 A JSONオブジェクト(JavaScriptのオブジェクト・リテラルの表現)

{ "PONumber"             : 1600,
  "Reference"            : "ABULL-20140421",
  "Requestor"            : "Alexis Bull",
  "User"                 : "ABULL",
  "CostCenter"           : "A50",
  "ShippingInstructions" : { "name"   : "Alexis Bull",
                             "Address": { "street"  : "200 Sporting Green",
                                          "city"    : "South San Francisco",
                                          "state"   : "CA",
                                          "zipCode" : 99236,
                                          "country" : "United States of America" },
                             "Phone" : [ { "type" : "Office", "number" : "909-555-7307" },
                                         { "type" : "Mobile", "number" : "415-555-1234" } ] },
  "Special Instructions" : null,
  "AllowPartialShipment" : false,
  "LineItems"            : [ { "ItemNumber" : 1,
                               "Part"       : { "Description" : "One Magic Christmas",
                                                "UnitPrice"   : 19.95,
                                                "UPCCode"     : 13131092899 },
                               "Quantity"   : 9.0 },
                             { "ItemNumber" : 2,
                               "Part"       : { "Description" : "Lethal Weapon",
                                                "UnitPrice"   : 19.95,
                                                "UPCCode"     : 85391628927 },
                               "Quantity"   : 5.0 } ] }

39.1.2 XMLと比較したJSONの概要

一般的に、JSONとXML (Extensible Markup Language)は両方ともデータ交換言語として使用されます。主な違いは次のとおりです。

  • JSONのデータ型は数が少なく、事前に定義されています。XMLデータは、型がないか、XML SchemaまたはDocument Type Definition (DTD)に基づいています。

  • JSONには、単純な構造定義および文書結合構造体がありますが、属性、名前空間、継承および代替はありません。

  • JavaScriptのオブジェクト・リテラルのメンバーの順序は重要ではありません。通常、順序が問題になるのはXML文書内です。

  • JSONには、XMLのテキスト・ノード(XPathノード・テストtext())に相当するものがありません。これは特に、混合コンテンツがないことを意味します。

JSONは、単純な構造データで使用する場合に最も役立ちます。XMLは、構造化されたデータと半構造化されたデータの両方で役立ちます。通常、JSONは文書中心ではなくデータ中心ですが、XMLはどちらにも対応しています。JSONはマークアップ言語ではなく、データ表現のみを目的として設計されています。XMLは、文書マークアップ言語とデータ表現言語の両方を兼ねています。

通常、JSONデータの方がXMLデータより、定義および機能が単純であるため、生成、解析および処理が簡単です。XMLにはモジュール性と継承の役に立つ名前空間および他の構造体が用意されているため、通常、様々なデータ・ソースの結合が関わるユースケースはXMLの使用に適しています。

JSONには、XML (またはJavaScript)とは異なり、日付データ型がありません。JSONでは、日付は文字列などの使用可能なデータ型を使用して表されます。実際の日付と文字列間における変換には、事実上の業界標準がいくつかあります。ただし、いずれにせよ、JSONを使用するプログラムでは日付表現の変換を処理する必要があります。

39.2 Oracle DatabaseにおけるJSONの概要

JSONデータとXMLデータは、Oracle Databaseでは同等の方法で使用できます。リレーショナル・データとは異なり、両方とも、データを定義するスキーマを必要とせずに格納、索引付けおよび問合せを行うことができます。Oracle Databaseは、トランザクション、索引付け、宣言的問合せおよびビューを含むリレーショナル・データベースの機能を使用してJSONをネイティブにサポートしています。

多くの場合、JSONデータは、Oracle NoSQL DatabaseおよびOracle Berkeley DBなどのNoSQLデータベースに格納されています。これらを使用すると、スキーマに基づいていないデータを格納および取得できますが、これらにはリレーショナル・データベースの厳密な整合性モデルは用意されていません。

このような短所を補うために、場合によっては、NoSQLデータベースと並行してリレーショナル・データベースが使用されます。したがって、NoSQLデータベースに格納されたJSONデータを使用するアプリケーションでは、データの整合性をそれ自体で確保する必要があります。

JSONがOracle Databaseでネイティブにサポートされることで、このような負荷を未然に防ぐことができます。トランザクション、索引付け、宣言的問合せおよびビューなどの、JSONで使用するためのリレーショナル・データベース機能のメリットすべてを利用できます。

Oracle Databaseの問合せは宣言的に行われます。JSONデータはリレーショナル・データに結合できます。また、JSONデータをリレーショナルに投影できるため、JSONデータはリレーショナルなプロセスおよびツールで使用できるようになります。さらに、データベースの外部で外部表に拡張されたJSONデータをデータベース内で問い合せることもできます。

データベースに格納されたJSONデータには、他のデータベース・データへのアクセスと同じ方法(OCI、.NETおよびJDBCの使用を含む)でアクセスできます。

SQLデータ型XMLTypeを使用して格納されるXMLデータとは異なり、JSONデータは、SQLデータ型VARCHAR2CLOBおよびBLOBを使用してOracle Databaseに格納されます。列値が有効なJSONインスタンスであることを確認するために、常にis_jsonチェック制約を使用することをお薦めします(例39-3を参照)。

データベース内のJSONデータはテキストですが、このテキストはデータ型BLOBのみでなくVARCHAR2またはCLOBを使用して格納できます。可能な場合、BLOB記憶域の使用をお薦めします。特に、そうするとキャラクタ・セット変換の必要がなくなります(「JSON: Oracle Databaseのキャラクタ・セットおよび文字エンコーディング」を参照してください)。

注意:

Hadoop Distributed File System (HDFS)に基づく外部表に格納されたJSONデータは、LOB記憶域が使用されている場合は、Oracle Big Data SQLにオフロードされません。Oracle Big Data Applianceソフトウェア・ユーザーズ・ガイドを参照してください。

JSONデータをBLOB列に格納する場合、JSONに対してOracle SQL関数または条件(json_valuejson_queryjson_tablejson_exists)を使用する問合せでキーワードFORMAT JSONを使用して、データがJSONであることを宣言する必要があります。これを行わない場合、エラーが発生し、JSON入力データがバイナリであり、その形式を指定していないことが通知されます。

注意:

JSONデータをBLOBまたはCLOB列に格納する場合は常に、この列に対してLOBキャッシュ・オプションをオンにすることをお薦めします。このオプションは、デフォルトで選択が解除されています。『Oracle Database SecureFilesおよびラージ・オブジェクト開発者ガイド』を参照してください。

定義上、テキストのJSONデータは、Unicodeエンコーディング(UTF-8またはUTF-16)を使用してエンコードされます。非Unicodeキャラクタ・セットで格納されたテキスト・データはJSONデータであるかのように使用できますが、この場合、このキャラクタ・セットはデータの処理時に自動的にUTF-8に変換されます。

SQLでは、Oracle Databaseに格納されたJSONデータには、次を使用してアクセスできます。

  • 関数json_valuejson_query and json_table

  • 条件json_existsis jsonis not jsonおよびjson_textcontains

  • json_valuejson_queryの組合せと同じように機能し、SQLオブジェクトのアクセス式と似たドット表記法(つまり、抽象データ型(ADT)の属性ドット表記法)。

単純な実例として、例39-2では単純なドット表記法を使用して、すべての発注書の要求者についてJSON列po_documentを問い合せています(JSONフィールドRequestor)。

例39-2 JSONデータの単純なSQL問合せ

SELECT po.po_document.Requestor FROM j_purchaseorder po;

39.2.1 Oracle DatabaseでJSONを使用する前に

一般的に、Oracle DatabaseでJSONデータを扱う場合に実行するタスクには、(1)is jsonチェック制約を使用したJSON列の作成、(2)列へのJSONデータの挿入、(3)JSONデータの問合せがあります。

  1. JSON列があるリレーショナル表を作成し、この列に整形式のJSONデータのみを確実に含めるためにis jsonチェック制約を追加します。

    次の文では、JSON列po_documentを使用してリレーショナル表j_purchaseorderを作成しています(例39-3も参照)。

    CREATE TABLE j_purchaseorder
       (id          RAW (16) NOT NULL,
        date_loaded TIMESTAMP WITH TIME ZONE,
        po_document CLOB
        CONSTRAINT ensure_json CHECK (po_document IS JSON));
    
  2. Oracle Databaseで使用可能な任意のメソッドを使用してJSON列にJSONデータを挿入します。

    次の文では、SQL INSERT文を使用して単純なJSONデータを挿入しています。ここでは、一部のデータが省略されています(...)。これらの詳細は、例39-4を参照してください。

    INSERT INTO j_purchaseorder
      VALUES (SYS_GUID(),
              SYSTIMESTAMP,
              '{"PONumber"             : 1600,
                "Reference"            : "ABULL-20140421",
                "Requestor"            : "Alexis Bull",
                "User"                 : "ABULL",
                "CostCenter"           : "A50",
                "ShippingInstructions" : {...},
                "Special Instructions" : null,
                "AllowPartialShipment" : true,
                "LineItems"            : [...]}');
    
  3. JSONデータを問い合せます。戻り値は常に、JSON値を表すVARCHAR2インスタンスです。ここでは、単純な例をいくつか示します。

    次の問合せでは、列po_document内の各JSON文書から、スカラー値(JSON列po_document内のオブジェクトのフィールドPONumberの値であるJSON数値)を抽出しています(例39-18も参照)。

    SELECT po.po_document.PONumber FROM j_purchaseorder po;
    

    次の問合せでは、JSON列po_document内の各文書から、JSON電話オブジェクトの配列(フィールドShippingInstructionsの値のフィールドPhoneの値)を抽出しています(例39-19も参照)。

    SELECT po.po_document.ShippingInstructions.Phone FROM j_purchaseorder po;
    

    次の問合せでは、各JSON文書から、複数の値(配列Phone内の各オブジェクトのフィールドtypeの値)を配列として抽出しています。戻される配列は、格納されているデータの一部ではありませんが、問合せによって自動的に構成されます。(配列要素の順序は指定されません。)

    SELECT po.po_document.ShippingInstructions.Phone.type FROM j_purchaseorder po;
    

39.3 JSON: Oracle Databaseのキャラクタ・セットおよび文字エンコーディング

テキストのJSONデータでは常にUnicodeキャラクタ・セットが使用されます。この点で、JSONデータの方がXMLデータより簡単に使用できます。これは、JSONデータ交換フォーマットの重要な部分です(RFC 4627)。Oracle Databaseで処理されるJSONデータでは、必要なキャラクタ・セットの変換が自動的に行われます。

Oracle Databaseでは、JSONデータの処理時にUTF-8を内部で使用します(解析、問合せ)。このような処理に入力されるデータまたはこのような処理から出力されるデータをUTF-8とは異なるキャラクタ・セットにする必要がある場合は、適切なキャラクタ・セット変換が自動的に実行されます。

キャラクタ・セット変換はパフォーマンスに影響する可能性があります。また、情報が失われる可能性もあります。入力データをUTF-8に変換する操作では情報が失われる可能性は高くありませんが、出力キャラクタ・セットで表すことができない文字の場合、出力への変換の結果として情報の損失が発生する可能性があります。

テキストのJSONデータがUnicodeのようにデータベースに格納されている場合、キャラクタ・セットの変換は必要ありません。これは、データベースのキャラクタ・セットがAL32UTF8 (Unicode UTF-8)である場合です。可能である場合、このようにすることをお薦めします。

テキストとして(つまり、文字として)格納されていないJSONデータでキャラクタ・セット変換が行われることはありません。この場合、変換する文字がありません。このことは、データ型BLOBを使用して格納されているJSONデータではキャラクタ・セット変換が行われないことを意味します。

JSONデータが非Unicodeキャラクタ・データとして格納されている(つまり、Unicode以外のVARCHAR2またはCLOBでの格納が使用されている)場合は、キャラクタ・セット変換を回避するために次の実行を検討してください。

関連項目:

  • Unicodeの詳細は、http://www.unicode.orgを参照してください。

  • JSONデータ交換フォーマットの詳細は、http://tools.ietf.org/html/rfc4627およびhttp://www.ecma-international.org/publications/standards/Ecma-404.htmを参照してください。

  • データベースでの様々なキャラクタ・セットの使用の詳細は、『Oracle Database Migration Assistant for Unicodeガイド』を参照してください。

  • データベースでのキャラクタ・セット変換の詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。

39.3.1 JSONデータ内のUnicode文字のエスケープ

ASCII文字は、Unicodeの最初の128文字に直接対応しています。アプリケーションでASCIIエスケープ・シーケンスを使用することにより、別の方法ではキャラクタ・セット変換が必要になる可能性がある入力Unicode文字を表すことができる場合、このような変換によって生じる可能性があるパフォーマンス・ペナルティまたは情報の紛失を回避できます。

Unicode文字に対するASCIIのエスケープ・シーケンスは、\uの後ろに、この文字のUnicodeコード・ポイントを表すASCIIの16進数字を4つ付けたものです。

たとえば、EURO SIGNという名前のUnicodeのユーロ文字€,はコード・ポイント20AC (16進数字を使用)を持つため、ASCIIのエスケープ・シーケンス\u20ACを使用して表すことができます。

入力データには明示的なASCIIのエスケープを使用できます。JSONデータにはUnicodeが内部で使用されるため、このデータが出力される場合、デフォルトではキャラクタ・セット変換が引き続き適用されます。ただし、Oracle SQL関数json_valuejson_queryおよびjson_tableの場合、キーワードASCIIを使用することにより、非ASCII Unicode文字に対してASCIIのエスケープ・シーケンスを自動的に使用するよう指定できます。

39.4 Oracle JSONパス式の概要

Oracle Databaseでは、Oracle SQLパス式を使用したJSONデータへのSQLアクセスが提供されます。

JSONは、JavaScript値の表記法です。JSONデータがデータベースに格納されている場合、XMLデータ用のXQueryまたはXPath式とある程度似たパス式を使用してこのデータを問い合せることができます。SQL/XMLでXQuery式を使用してXMLデータに対するSQLのアクセスが許可されるのと同じように、Oracle Databaseでは、Oracle JSONパス式を使用してJSONデータに対するSQLのアクセスが提供されます。

Oracle JSONパス式の構文は単純です。Oracle JSONパス式では、この式と一致するかこの式を満たす0個以上のJSON値が選択されます。

Oracle SQL条件json_existsの場合、少なくとも1つの値が一致する場合はtrueが戻され、一致する値がない場合はfalseが戻されます。単一の値が一致した場合、この値がスカラーである場合はSQL関数json_valueによってこの値が戻され、スカラーでない場合はエラーが発生します。パス式に一致する値がない場合は、json_valueによってSQL NULLが戻されます。

Oracle SQL関数json_queryは、一致する値をすべて戻します。つまり、この関数は複数の値を戻すことができます。この動作は、XQueryの場合のように値のシーケンスを戻す動作とみなすことも、複数の値を戻す動作とみなすこともできます。(ユーザーから見えるシーケンスが現れることはありません。)

どのような場合でも、パス式の照合では、パス式の各ステップを順番に照合しようとします。いずれかのステップの照合が失敗すると、後続のステップの照合は行われず、パス式の照合は失敗します。各ステップの照合が成功すると、パス式の照合は成功します。

関連項目:

パス式のステップの詳細は、「Oracle JSONパス式の構文」を参照してください。

39.4.1 Oracle JSONパス式の構文

Oracle SQLパス式は、パスの部分を選択するためにOracle SQLファンクションおよび条件によってJSONデータと照合されます。パス式にはワイルドカードおよび配列範囲を使用できます。

Oracle JSONパス式およびJSONデータをOracle SQL関数または条件に渡します。パス式はデータに対して照合され、一致するデータが特定のSQL関数または条件によって処理されます。この照合プロセスは、パス式が一致データを関数または条件に戻すという観点で検討することができます。

39.4.1.1 Oracle JSONパス式の基本的な構文

Oracle JSONパス式の基本的な構文は、次のとおりです。コンテキスト項目の性質に応じて、コンテキスト項目、0(ゼロ)または複数のオブジェクト・ステップまたは配列ステップ構成されます。例を示します。

ただし、この基本的な構文は、非配列パターンに対する配列の照合および配列パターンに対する非配列の照合の緩和によって拡張されます。「Oracle JSONパス式の構文の緩和」を参照してください。

  • Oracle JSONパス式は、パス式のコンテキスト項目(つまり、照合するJSONデータ)を表すドル記号($)から始まります。このデータは、Oracle SQL関数に引数として渡されたSQL式の評価結果です。

    ドル記号の後ろには0個以上のステップが続き、これらの各ステップは、コンテキスト項目がJSONオブジェクトとJSON配列のどちらを表すかに応じてオブジェクト・ステップまたは配列ステップになります。

  • オブジェクト・ステップは、場合によっては"ドット"と呼ばれるピリオド(.)の後ろに、オブジェクト・プロパティ(キー)名、またはすべてのフィールド(の値)を表すアスタリスク(*)ワイルドカードが付いた形式です。キー名は、大文字または小文字の文字A-Zで始まり、このような文字または10進数字(0-9)のみを含む必要があり、それ以外の場合は、二重引用符(")で囲む必要があります。オブジェクト・ステップは、指定されたキーのを戻します。キーにワイルドカードが使用されている場合、すべてのキーのが特に順序は指定されずに戻されます。

  • 配列ステップは、左大カッコ([)の後ろに、すべての配列要素を表すアスタリスク(*)ワイルドカードまたはカンマで区切られた1つ以上の特定の配列索引または範囲指定のどちらかが続き、その後ろに右大カッコ(])が付いた形式です。パス式では、配列に対するJavaScript変換の場合のように、配列索引付けは0を基準として行われます(0、1、2、...)。範囲指定の形式はNからMであり、NおよびMは配列索引であり、Nは必ずMより小さい値である必要があります。(NMより小さい値でない場合、問合せのコンパイル時にエラーが発生します。)アスタリスクと配列索引または範囲指定の両方を使用すると、エラーが発生します。

    索引または範囲指定を使用する場合、一括して指定される配列要素は、反復せずに昇順で指定する必要があり、そうでない場合はコンパイル時にエラーが発生します。たとえば、[3, 1 to 4][4, 2][2, 3 to 3]および[2, 3, 3]のそれぞれについてエラーが発生しますが、最初の2つの場合は順序が昇順でないことが原因であり、最後の2つの場合は3が反復していることが原因です。

    同様に、照合の結果として生じる配列値内の要素は昇順であり、反復は行われません。パス式にアスタリスクが使用される場合、すべての配列要素が配列順序で戻されます。

パス式の例を次に示しますが、その意味も詳述しています。

  • $ - コンテキスト項目。

  • $.friends - コンテキスト項目オブジェクトのキーfriendsの値。ドット付きの表記法は、コンテキスト項目がJSONオブジェクトであることを示します。

  • $.friends[0] - コンテキスト項目オブジェクトのキーfriendsの値である配列の最初の要素であるオブジェクト。大カッコ表記法は、キーfriendsの値が配列であることを示します。

  • $.friends[0].name - コンテキスト項目オブジェクトのキーfriendsの値である配列の最初の要素であるオブジェクトのキーnameの値。2番目のドットは、配列friendsの最初の要素が(キーnameを持つ)オブジェクトであることを示します。

  • $.friends[*].name - コンテキスト項目オブジェクトのキーfriendsの値である配列のオブジェクトのキーnameの値。

  • $.*[*].name - コンテキスト項目オブジェクトのキーの配列値の各オブジェクトのキーnameの値。

  • $.friends[3, 8 to 10, 12] - 配列friends (コンテキスト項目オブジェクトのキー)の12番目、3番目、8番目、9番目および10番目の要素。要素は昇順に指定する必要があり、戻される順序は、3番目、8番目、9番目、10番目、12番目の順です。

  • $friends[3].cars - 配列friendsの3番目の要素であるオブジェクトのキーcars。ドットは、3番目の要素が(キーcarsを持つ)オブジェクトであることを示します。

  • $friends[3].* - 配列friendsの3番目の要素であるオブジェクトのすべてのキーの値。

  • $friends[3].cars[0].year - 変数friendsにバインドされている配列の3番目の要素であるオブジェクトのキーcarsの値である配列の最初の要素であるオブジェクトのキーyearの値。

39.4.1.2 Oracle JSONパス式の構文の緩和

暗黙的な配列のラップおよびアンラップを可能にするため、Oracle SQLパス式の基本的な構文は緩和されています。これは、データが発展して特定のJSON値のかわりにこのような値の配列が使用される(またはこの逆)場合、コード内のパス式を変更する必要がないことを意味します。例を示します。

「Oracle JSONパス式の基本的な構文」では、Oracle JSONパス式の基本的な構文を定義しています。サポートされている実際のパス式の構文では、この定義を次のように緩和します。

  • パス式のステップが配列を対象としている(予測している)が、実際のデータは配列を示していない場合、データは暗黙的に配列にラップされます。

  • パス式のステップが非配列を対象としている(予測している)が、実際のデータは配列を示している場合、配列タは暗黙的にアンラップされます。

この緩和により、次の省略が可能になります。すなわち、[*]は、オブジェクト・アクセッサ.の前にあり、オブジェクト・フィールド名が後ろに続く場合は常に省略でき、本質的に何の変更も行われません。この逆もまた真です。[*]は、オブジェクト・アクセッサ.の前に常に挿入でき、本質的に何の変更も行われません。

つまり、特定のオブジェクトの配列の各要素のフィールドpropの値を表すオブジェクト・ステップ[*].prop.propとして省略でき、単一オブジェクトのprop値を表すかのように見えるオブジェクト・ステップ.propは、オブジェクト・アクセッサが適用された配列の各要素のprop値も表します。

これは重要な機能です。なぜなら、データが発展して特定のJSON値のかわりにこのような値の配列が使用される(またはこの逆)場合、コード内のパス式を変更する必要がないからです。

たとえば、フィールドtypeおよびnumberを伴う単一オブジェクトが値であるフィールドPhoneを持つオブジェクトがデータにもともと含まれるときに、このデータが発展して電話の配列を表す場合、単一の電話番号と一致するパス式$.Phone.numberを引き続き使用できます。パス式$.Phone.numberは、番号を選択して単一の電話オブジェクトと一致することも、各番号を選択して電話オブジェクトの配列と一致することもできます。

同様に、データに両方の種類の表現が混在する(単一の電話オブジェクトを使用するデータ・エントリ、および電話オブジェクトの配列を使用するエントリ、または両方を使用するエントリさえも存在する)場合、同じパス式を使用して、これらの異なる種類のエントリの電話情報にアクセスできます。

次に、「Oracle JSONパス式の基本的な構文」の項のパス式の例を、相当する式の説明とともに示します。

  • $.friends – 次のいずれかのフィールドfriendsの値。

    • (単一の)コンテキスト項目オブジェクト。

    • ($[*].friendsに相当)コンテキスト項目配列内の各オブジェクト。

  • $.friends[0].name - 次のオブジェクトのいずれかのフィールドnameの値。

    • コンテキスト項目オブジェクトのフィールドfriendsの値である配列の最初の要素。

    • ($.friends.nameに相当)コンテキスト項目オブジェクトのフィールドfriendsの値。

    • ($[*].friends.nameに相当)コンテキスト項目配列の各オブジェクトのフィールドfriendsの値。

    • ($[*].friends[0].nameに相当)コンテキスト項目配列の各オブジェクトのフィールドfriendsの値である各配列の最初の要素。

    コンテキスト項目はオブジェクトでもオブジェクトの配列でもかまいません。後者の場合、配列内の各オブジェクトはフィールドfriendsについて照合されます。

    フィールドfriendsの値はオブジェクトでもオブジェクトの配列でもかまいません。後者の場合、配列内の最初のオブジェクトが使用されます。

  • $.*[*].name – 次のオブジェクトのいずれかのフィールドnameの値。

    • コンテキスト項目オブジェクトのフィールドの配列値の要素。

    • ($.*.nameに相当)コンテキスト項目オブジェクトのフィールドの値。

    • ($[*].*.nameに相当)コンテキスト項目配列のオブジェクトのフィールドの値。

    • ($[*].*[*].nameに相当)コンテキスト項目配列のオブジェクトのフィールドの配列値の各オブジェクト。

39.5 JSONデータで使用するためのOracle SQL関数および条件

Oracle Databaseには、格納されているJSONデータを作成、問合せおよび操作するために使用可能なSQL関数および条件が用意されています。これらの一部では、リテラルのSQL文字列としてのOracle JSONパス式の後ろに場合によってはRETURNING句、ラッパー句またはエラー句が続いたものが引数として使用されます。

  • Oracle SQL条件IS JSONおよびIS NOT JSON - データが整形式のJSONデータであるかどうかをテストします。特にチェック制約として使用されます。

  • Oracle SQL条件JSON_EXISTS - JSONデータ内に特定の値が存在するかどうかをテストします。

  • Oracle SQL関数JSON_VALUE - SQL値としてスカラー値をJSONデータから選択します。

  • Oracle SQL関数JSON_QUERY - JSON値を表すSQL文字列として1つ以上の値をJSONデータから選択します。特に、JSON文書のフラグメント(通常はJSONオブジェクトまたは配列)を取得するために使用されます。

  • Oracle SQL関数JSON_TABLE - JSONデータを仮想表としてリレーショナル形式に投影します(これは、インライン・リレーショナル・ビューとみなすこともできます)。

関連項目:

39.5.1 JSON用のOracle SQL関数および条件で使用される句

RETURNING、ラッパー、およびエラー処理について説明します。これらは、Oracle SQLファンクションおよび条件のjson_valuejson_queryjson_tableis jsonis not jsonおよびjson_existsの1つ以上で使用されます。

39.5.1.1 JSON用のOracle SQL関数のRETURNING句

Oracle SQLファンクションjson_valueおよびjson_queryは、オプションでRETURNING句を受け入れます。この句は、関数から返される値のデータ型を指定します。この句についてと、デフォルト動作(RETURNING句なし)について説明します。

json_valueの場合、VARCHAR2またはNUMBERRETURNING句で使用できます。 json_queryの場合、使用できるのはVARCHAR2のみです。

必要に応じて、VARCHAR2の長さ(デフォルト: 4000)、およびNUMBERの精度とスケールを指定できます。

デフォルトの動作(RETURNING句なし)では、VARCHAR2(4000)を使用します。

また、RETURNING句は、PRETTYおよびASCIIの2つのオプションのキーワードも受け入れます。両方を使用する場合は、PRETTYASCIIの前にくる必要があります。ASCIIは、Oracle SQL関数json_valueおよびjson_queryでのみ使用できます。PRETTYは、json_queryでのみ使用できます。

キーワードPRETTYを使用すると、改行文字の挿入およびインデントにより、戻されたデータがわかりやすいように出力されます。デフォルトの動作では、わかりやすいようには出力されません。

キーワードASCIIを使用すると、標準のASCII Unicodeエスケープ・シーケンスを使用することにより、戻されるデータ内の非ASCII Unicode文字がすべて自動的にエスケープされます。デフォルトの動作では、非ASCII Unicode文字はエスケープされません。

ヒント:

パス式として$のみを使用することにより、コンテキスト項目全体をわかりやすいように出力できます。

39.5.1.2 Oracle SQL関数JSON_QUERYおよびJSON_TABLEのラッパー句

Oracle SQLファンクションのjson_queryおよびjson_tableは、オプションのラッパー句を受け入れます。これには、json_queryによって返される値、またはjson_tableリレーショナル列のデータに使用される値の形式を指定します。この句についてと、デフォルト動作(ラッパー句なし)について説明します。例を示します。

ラッパー句は、次のいずれかの形式をとります。

  • WITH WRAPPER - パス式と一致するすべてのJSON値が含まれるJSON配列を表す文字列値を使用します。配列要素の順序は指定されません。

  • WITHOUT WRAPPER - パス式と一致する単一のJSONオブジェクトまたは配列を表す文字列値を使用します。パス式がスカラー値(オブジェクトまたは配列ではありません)または複数の値と一致する場合、エラーが発生します。

  • WITH CONDITIONAL WRAPPER - パス式と一致するすべてのJSON値を表す文字列値を使用します。0個の値、単一のスカラー値、または複数の値の場合、WITH CONDITIONAL WRAPPERWITH WRAPPERと同じです。単一のJSONオブジェクトまたは配列値の場合は、WITHOUT WRAPPERと同じです。

デフォルトの動作はWITHOUT WRAPPERです。

オプションのキーワードUNCONDITIONALは、これを使用する方が明確になる場合はキーワードWITHの直後に追加できます。WITH WRAPPERWITH UNCONDITIONAL WRAPPERは同じことを意味します。

オプションのキーワードARRAYは、これを使用する方が明確になる場合はキーワードWRAPPERの直前に追加できます。WRAPPERARRAY WRAPPERは同じことを意味します。

表39-1は、ラッパー句の使用可能性を示しています。配列ラッパーは太字で示されています。

表39-1 JSON_QUERYラッパー句の例

パス式と一致するJSON値 WITH WRAPPER WITHOUT WRAPPER WITH CONDITIONAL WRAPPER

{"id": 38327} (単一のオブジェクト)

[{"id": 38327}]

{"id": 38327}

{"id": 38327}

[42, "a", true] (単一の配列)

[[42, "a", true]]

[42, "a", true]

[42, "a", true]

42

[42]

エラー(スカラー)

[42]

42, "a", true

[42, "a", true]

エラー(複数の値)

[42, "a", true]

なし

[]

エラー(値なし)

[]

たとえば、JSONオブジェクトを取得するためのjson_query問合せを検討してみます。パス式がオブジェクトではなくJSONスカラー値と一致した場合、または複数のJSON値(任意の種類)と一致した場合はどうなるでしょうか。エラーを発生させずに、一致した値を取得したい場合があります。たとえば、オブジェクトである値の1つを選択し、さらに処理したい場合があります。配列ラッパーを使用すると、このような処理を行うことができます。

ラッパーを使用する理由がエラーの発生を回避することのみであり、これらのエラー事例をエラーでない事例と区別する必要がない場合、条件付きラッパーが役立ちます。アプリケーションが探しているものが単一のオブジェクトまたは配列であり、パス式によって一致したデータがそのものである場合、予期した値を単一の配列にラップする必要はありません。

一方、無条件ラッパーの場合、結果として生成される配列は常にラッパーであることが判明しています。アプリケーションはこの事実に頼ることができます。条件付きラッパーを使用する場合、アプリケーションでは、戻された配列を解析するために追加の処理を行う必要がある場合があります。たとえば、表39-1では、同じ配列([42, "a", true])が、この配列と一致するパス式、およびその各要素と一致するパス式という、まったく異なる事例に対して戻されています。

39.5.1.3 JSON用のOracle SQL関数および条件のエラー句

JSONの一部のSQL関数および条件は、オプションでエラー句を受け入れます。これにより、Oracle SQL関数または条件によって発生したエラーの処理方法を指定します。この句についてと、デフォルト動作(エラー句なし)について説明します。

オプションのエラー句により、Oracle SQL関数または条件によって発生したエラーの処理方法を指定します。

この句は、次のいずれかの形式をとります。

  • ERROR ON ERROR - エラーを発生させます(特別な処理なし)。

  • NULL ON ERROR - エラーを発生させるかわりにNULLを戻します。

  • TRUE ON ERROR - エラーを発生させるかわりにtrueを戻します。この形式の句が使用可能なのは、Oracle SQL条件json_existsの場合のみです。

  • FALSE ON ERROR - エラーを発生させるかわりにfalseを戻します。この形式の句が使用可能なのは、Oracle SQL条件json_existsの場合のみです。

  • EMPTY ON ERROR - エラーを発生させるかわりに空の配列([])を戻します。この形式の句が使用可能なのは、Oracle SQL関数json_queryの場合のみです。

  • DEFAULT 'literal_return_value' ON ERROR - エラーを発生させるかわりに指定した値を戻します。値は、問合せのコンパイル時に定数である必要があります。

    この形式の句は、json_queryでは使用できません。

デフォルトの動作はNULL ON ERRORです。

注意:

ON ERROR句は、構文的に正しいOracle JSONパス式がJSONデータに対して照合されたときに発生する実行時エラーに対してのみ有効です。構文的に正しくないパス式の場合、コンパイル時エラーが発生します。これは、ON ERROR句によっては処理されません。

39.5.2 Oracle SQL条件IS JSONおよびIS NOT JSON

Oracle SQL条件is jsonおよびis not jsonは補足的な条件です。これらは、引数がJSONデータとして構文的に正しい(つまり、整形式である)かどうかをテストします。これらは、SELECT文のCASE式またはWHERE句で使用できます。

引数が構文的に正しい場合、is jsonはtrueを戻し、is not jsonはfalseを戻します。引数がなんらかの理由(解析中にエラーが発生した場合など)によって評価できない場合、データは単に整形式でないとみなされます。この場合、is jsonによってfalseが戻され、is not jsonによってtrueが戻されます。整形式とは、データが構文的に正しいことを意味します。(JSONデータは、厳密な構文と緩慢な構文と呼ばれる2つの概念の整形式にすることができます。)

関連項目:

39.5.2.1 列にJSONデータが含まれることを確認するためのチェック制約の使用

SQL条件is jsonの一般的な使用方法は、JSON列のデータが(整形式の) JSONデータであることを確認するためのチェック制約として使用する方法です。JSONデータを対象とした列を作成する場合は常にis_jsonチェック制約を使用することをお薦めします。

例39-3および例39-4に、これを示します。これらの例では、別の場所にある例で使用されるデータを保持する表を作成し、データを入力します。

例39-4では、簡潔にするために、1行のデータ(1つのJSON文書)のみが挿入されています。完全なデータ・セットを挿入する例は、「外部JSONデータのロード」を参照してください。

注意:

Oracle SQL条件IS JSONおよびIS NOT JSONは、NULL以外のSQL値に対してはtrueまたはfalseを戻します。ただし、これらは両方とも、SQLのNULLに対してはunknown (trueでもfalseでもありません)を戻します。チェック制約で使用される場合、NULL値の挿入が阻止されることはありません。ただし、SQLのWHERE句で使用される場合、NULLは選択されません(戻されません)。

チェック制約によってデータ挿入のパフォーマンスが低下することは事実です。特定の列に整形式のJSONデータのみが挿入されることが確実である場合、チェック制約を無効にすることを検討できますが、制約は削除しないでください

関連項目:

例39-3 JSONデータが整形式であることを確認するためのチェック制約でのIS JSONの使用

CREATE TABLE j_purchaseorder
   (id          RAW (16) NOT NULL,
    date_loaded TIMESTAMP (6) WITH TIME ZONE,
    po_document CLOB
    CONSTRAINT ensure_json CHECK (po_document IS JSON));

例39-4 JSON列のあるリレーショナル表へのデータの挿入

INSERT INTO j_purchaseorder
  VALUES (
    SYS_GUID(),
    SYSTIMESTAMP,
    '{"PONumber"             : 1600,
      "Reference"            : "ABULL-20140421",
      "Requestor"            : "Alexis Bull",
      "User"                 : "ABULL",
      "CostCenter"           : "A50",
      "ShippingInstructions" : {"name"   : "Alexis Bull",
                                "Address": {"street"  : "200 Sporting Green",
                                            "city"    : "South San Francisco",
                                            "state"   : "CA",
                                            "zipCode" : 99236,
                                            "country" : "United States of America"},
                                "Phone" : [{"type" : "Office", "number" : "909-555-7307"},
                                           {"type" : "Mobile", "number" : "415-555-1234"}]},
      "Special Instructions" : null,
      "AllowPartialShipment" : true,
      "LineItems"            : [{"ItemNumber" : 1,
                                 "Part"       : {"Description" : "One Magic Christmas",
                                                 "UnitPrice"   : 19.95,
                                                 "UPCCode"     : 13131092899},
                                 "Quantity"   : 9.0},
                                {"ItemNumber" : 2,
                                 "Part"       : {"Description" : "Lethal Weapon",
                                                 "UnitPrice"   : 19.95,
                                                 "UPCCode"     : 85391628927},
                                 "Quantity"   : 5.0}]}');

39.5.2.2 列にJSONデータが必然的に含まれるかどうかの確認

データが整形式のJSONデータであることを確認するチェック制約が特定の列に設定されているかどうかは、どうすれば確認できるでしょうか。この場合、この列はDBA_JSON_COLUMNSUSER_JSON_COLUMNSおよびALL_JSON_COLUMNSの静的データ・ディクショナリ・ビューにリストされます。

各ビューには、所有者の名前、表、列、および列のデータ型がリストされます。このデータを問い合せることにより、JSON列を検索できます。Foot 5

データがJSONデータであることを確認するチェック制約が無効である場合でも、列はビュー内にリストされたままです。チェック制約が削除されている場合、列はビューから削除されます。

39.5.2.3 JSONオブジェクトの一意フィールドと重複フィールド

デフォルトでは、指定のJSONオブジェクトに対してオブジェクト・フィールド(オブジェクト・プロパティ)が一意である必要はありませんが、特定のJSONデータに重複するフィールド名を持つオブジェクトがない場合のみ、このJSONデータが整形式であるとみなすように指定することもできます。

JSON標準では、特定のJSONオブジェクトに対してフィールド名が一意である必要があるかどうかは指定されません。つまり、このことは先験的に、整形式のJSONオブジェクトには同じフィールド名を持つ複数のメンバーを設定できることを意味します。これは、Oracle DatabaseでJSONデータを処理する場合のデフォルトの動作です。

特定のJSONデータに含まれるすべてのオブジェクトが一意のフィールド名を持つ(つまり、重複するフィールド名を持つオブジェクトがない)場合のみ、このJSONデータが整形式であるとみなすように指定できます。これは、Oracle SQL条件is jsonでキーワードWITH UNIQUE KEYSを使用することで行います。脚注 6UNIQUE KEYSを指定しないか、キーワードWITHOUT UNIQUE KEYSを使用する場合、オブジェクトが重複フィールド名を持ったままでも整形式であるとみなすことができます。

Oracle Databaseで採用されている評価では常に、特定のフィールド名を持つオブジェクト・メンバーの1つのみが使用されます。同じフィールド名を持つ他のメンバーは無視されます。このような複数のメンバーのうちどれが使用されるかは指定されていません。

整形式のJSONデータで重複フィールド名が許可されるかどうかは、整形式かどうかの確認に、厳密な構文と緩慢な構文のどちらが使用されるかとかかわっています。

39.5.2.4 厳密なJSON構文と緩慢なJSON構文について

JSON向けのOracleのデフォルト構文は緩慢です。特に、この構文は、オブジェクト・フィールドに対してJavaScript構文を反映し、ブール型の値およびnull値では大/小文字が区別されず、数字、ホワイトスペースおよびUnicode文字のエスケープについてはより寛容です。

標準ECMA-404のJSONデータ交換フォーマット、およびECMA-262のECMAScript言語指定により、JSON構文が定義されます。

これらの指定に応じて、各JSONのフィールドおよび各文字列値は、二重引用符(")で囲む必要があります。Oracleではこの厳密なJSON構文をサポートしていますが、これはデフォルトの構文ではありません

JavaScript表記法では、オブジェクト・リテラルで使用されるフィールドは、二重引用符で囲むことができますが、必須ではありません。これはまた、一重引用符(')で囲むこともできます。Oracleではこの緩慢なJSON構文もサポートしており、これがデフォルトの構文です。

また、実際に、一部のJavaScript実装(ただし、JavaScript標準ではありません)では次の1つ以上が許可されています。

  • キーワードtruefalseおよびnullの大/小文字の相違(TRUETrueTrUefALSeNulLなど)。

  • 配列の最後の要素またはオブジェクトの最後のメンバーの後ろに追加されるカンマ(,) ([a, b, c,]{a:b, c:d,}など)。

  • 先頭に1つ以上の0がある数字(0042.3など)。

  • 小数点の前に0がない小数(0.14ではなく.14など)。

  • 小数点の後に小数部分がない数字(342.1.e27など)。

  • 数値がマイナスではないことを意味する、数字の前のプラス記号(+) (+1.3など)。

この構文も、Oracleのデフォルトの(緩慢な) JSON構文の一部として許可されます。(厳密な数字構文は、JSON標準を参照してください。)

ASCIIのスペース文字(U+0020)以外にも、JSON標準では、引用符で囲まれたフィールドまたは文字列値の外側で使用される場合、次の文字は重要でない(無視される)ホワイトスペースとして定義されています。

  • タブ、水平タブ(HT ^I、10進数の9、U+0009、\t)

  • 行送り、改行(LF ^J、10進数の10、U+000A、\n)

  • キャリッジ・リターン(CR ^M、10進数の13、U+000D、\r)

ただし、Oracle JSONの緩慢な構文では、ASCII制御文字(0-31)のすべて、およびASCIIスペース文字(10進数の32、U+0020)は(重要でない)ホワイトスペース文字として処理されます。制御文字には次のようなものがあります。

  • Null (NUL ^@、10進数の0、U+0000、\0)

  • ベル(NEL ^G、10進数の7、U+0007、 \a)

  • 垂直タブ(VT ^K、10進数の11、U+000B)

  • エスケープ(ESC ^[、10進数の27、U+001B、\e)

  • 削除(DEL ^?、10進数の127、U+007F)

ASCIIのスペース文字(U+0020)は、引用符で囲まれたフィールドまたは文字列値内で許可されてエスケープされていない唯一のホワイトスペース文字です。これは、厳密なOracle JSON構文と緩慢なOracle JSON構文の両方に対して当てはまります。

厳密なOracle JSON構文と緩慢な構文の両方において、引用符で囲まれたオブジェクト・フィールドおよび文字列値に含めることができるのはUnicode文字のみですが、これらの一部は次のようにエスケープする必要があります。

  • ASCII制御文字は許可されていませんが、\b (バックスペース)、\f (フォーム・フィード)、\n (改行、行送り)、\r (キャリッジ・リターン)および\t (タブ、水平タブ)の各エスケープ・シーケンスによって表される文字は除きます。

  • 二重引用符(")、スラッシュ(/)およびバックスラッシュ(\)文字もエスケープする(バックスラッシュを前に置く)必要があります(それぞれ\"\/および\\)。

緩慢なOracle構文では、引用符で囲まれていないオブジェクト・フィールドに、ホワイトスペースとJSON構造文字(左右の大カッコ([])と中カッコ({})、コロン(:)およびカンマ(,))を除く任意のUnicode文字を含めることができますが、エスケープ・シーケンスは許可されません。

名前または文字列にも任意のUnicode文字を含めることができますが、この場合、Unicodeコード・ポイントを表す4つのASCIIの16進数字を後ろに付けたASCIIのエスケープ構文\uを使用します。

厳密なOracle JSON構文と緩慢なOracle JSON構文のいずれにおいても、出力可能でないかホワイトスペースとして表示される可能性がある他のUnicode文字(ノーブレークスペース文字(U+00A0)など)はホワイトスペースとみなされません

表39-2は、JSON構文のいくつかの例を示しています。

表39-2 JSONオブジェクト・フィールドの構文例

整形式かどうか

"part number": 1234

緩慢および厳密: はい。スペース文字は許可されます。

part number: 1234

緩慢(および厳密): いいえ。引用符で囲まれていない名前では、スペース文字を含むホワイトスペース文字は許可されません。

"part\tnumber": 1234

緩慢および厳密: はい。タブ文字のエスケープ・シーケンスは許可されます。

"part    number": 1234

緩慢および厳密: いいえ。エスケープされていないタブ文字は許可されません。エスケープされていないホワイトスペース文字で許可されるのはスペースのみです。

"\"part\"number": 1234

緩慢および厳密: はい。名前が引用符で囲まれている場合、エスケープされている二重引用符は許可されます。

\"part\"number: 1234

緩慢および厳密: いいえ。名前は引用符で囲む必要があります。

'\"part\"number': 1234

緩慢: はい、厳密: いいえ。一重引用符で囲まれた名前(オブジェクト・フィールドと文字列)は、緩慢な構文でのみ許可されます。引用符で囲まれた名前では、エスケープされている二重引用符が許可されます。

"pärt number":1234

緩慢および厳密: はい。引用符で囲まれた名前では、任意のUnicode文字が許可されます。

part:number:1234

緩慢(および厳密): いいえ。引用符で囲まれている名前では、構造文字は許可されません。

"pärt:number":1234

緩慢: はい、厳密: いいえ。引用符で囲まれている名前でホワイトスペース以外の構造文字およびUnicode文字が許可されるのは、緩慢な構文の場合のみです。

関連項目:

39.5.2.5 厳密なOracle JSON構文と緩慢なOracle JSON構文の指定

デフォルトのOracle JSON構文は緩慢です。構文が厳密か緩慢かが問題になるのは、SQL条件is jsonおよびis not jsonの場合のみです。他のすべてのOracle SQL関数および条件では、入力を解析するために緩慢な構文が使用され、出力を戻すために厳密な構文が使用されます。

特定のJSON入力データに厳密に正しい構文が使用されていることを確認する必要がある場合は、最初にis jsonまたはis not jsonを使用してチェックしてください。

JSON標準に応じてデータを厳密な整形式としてチェックするよう指定するには、(STRICT) (カッコを含む)をis jsonまたはis not json式に追加します。

例39-5に、これを示します。これは例39-3と同じですが、列に挿入されたすべてのデータがJSON標準に応じた整形式であることを確認するために(STRICT)が使用されています。

例39-5 JSONデータが厳密な整形式(標準)であることを確認するためのチェック制約でのIS JSONの使用

CREATE TABLE j_purchaseorder
   (id          RAW (16) NOT NULL,
    date_loaded TIMESTAMP WITH TIME ZONE,
    po_document CLOB
    CONSTRAINT ensure_json CHECK (po_document IS JSON (STRICT)));

39.5.3 Oracle SQL条件JSON_EXISTS

Oracle SQL条件json_existsでは、Oracle JSONパス式を行フィルタとして使用して、JSON文書の内容に基づいて行を選択できます。条件json_existsは、SELECT文のCASE式またはWHERE句で使用できます。

条件json_existsは、JSONデータ内に特定の値が存在するかどうかをチェックします。値が存在する場合はtrueが戻され、存在しない場合はfalseが戻されます。より正確に言うと、json_existsでは、対象とするデータが1つ以上のJSON値と一致する場合はtrueが戻されます。一致するJSON値がない場合は、falseが戻されます。

また、json_existsを使用して、JSONデータで使用するビットマップ索引を作成することもできます。例39-20を参照してください。

エラー・ハンドラERROR ON ERRORFALSE ON ERRORおよびTRUE ON ERRORが適用されます。デフォルトはFALSE ON ERRORです。このハンドラが有効になるのはエラーが発生したときですが、通常、エラーが発生するのは、特定のJSONデータが(緩慢な構文を使用した)整形式でない場合です。条件is jsonおよびis not jsonの事例とは異なり、条件json_existsでは、検査するデータが整形式のJSONデータであることを予期しています。

json_existsの2番目の引数は、Oracle JSONパス式の後ろにオプションのRETURNING句とオプションのエラー句が付いた形式です。このパス式では単一のスカラー値を対象とする必要があり、そうでない場合、コンパイル時にエラーが発生します。

注意:

JSON値nullに適用されたOracle SQL条件json_existsは、SQL文字列'true'を戻します。

関連項目:

39.5.3.1 JSON_TABLEとしてのJSON_EXISTS

Oracle SQL条件json_existsは、Oracle SQL関数json_tableの特別な事例であるとみなすことができます。

例39-6に、この対応を示します。2つのSELECT文で得られる結果は同じになります。

この対応は、おそらくjson_existsについてより深く理解する手助けとなるのみでなく、どちらを使用しても同じ結果が得られることを意味しているため、実質的に重要な意味を持ちます。

特に、json_existsを複数回使用する場合、またはこれをjson_valueまたはjson_query (これらもjson_tableを使用して表すことができます)と組み合せて使用して同じデータにアクセスする場合、json_tableを1回呼び出す方が、データが解析されるのが1回のみであるという利点があります。

このため、オプティマイザがjson_existsjson_valueおよびjson_queryの複数の呼出し(任意の組合せ)を、より少ないjson_tableの呼出しに自動的にリライトすることがよく起こります。

例39-6 JSON_TABLEを使用して表されたJSON_EXISTS

SELECT select_list
  FROM table WHERE json_exists(column, json_path error_handler ON ERROR);
       
SELECT select_list
  FROM table,
       json_table(column, '$' error_handler ON ERROR
         COLUMNS ("COLUMN_ALIAS" NUMBER EXISTS PATH json_path)) AS "JT"
  WHERE jt.column_alias = 1;

39.5.4 Oracle SQL関数JSON_VALUE

Oracle SQL関数json_valueは、JSONデータからscalar値を選択し、これをSQL値として戻します。

また、json_valueを使用して、JSONデータで使用する関数ベースのBツリー索引を作成することもできます。「JSONデータの索引」を参照してください。

関数json_valueは、2つの必須引数を持ち、オプションのRETURNING句およびエラー句を受け入れます。

json_valueの最初の引数は、スカラーのSQLデータ型のインスタンスを戻すSQL式です(つまり、オブジェクト・データ型でもコレクション・データ型でもありません)。これは、データ型VARCHAR2BLOBまたはCLOBのいずれかになります。これは、適切にキャストされた表またはビューの列の値、PL/SQL変数、バインド変数のいずれかになります。SQL式の評価の結果は、パス式を評価するためのコンテキスト項目として使用されます。

json_valueの2番目の引数は、Oracle JSONパス式の後ろにオプションのRETURNING句とオプションのエラー句が付いた形式です。このパス式では単一のスカラー値を対象とする必要があり、そうでない場合、エラーが発生します。

デフォルトのエラー処理動作はNULL ON ERRORであり、これは、エラーが発生しても値が戻されない、つまり、エラーが発生しないことを意味します。特に、パス式が配列などの非スカラー値を対象としている場合、デフォルトではエラーは発生しません。エラーが発生するようにするには、ERROR ON ERRORを使用します。

注意:

特定のJSONオブジェクト内のフィールド名は、それぞれが一意である必要はありません。同じフィールド名を繰り返すことができます。Oracle Databaseで行われるストリーム評価では、特定のフィールド名を持つ1つのオブジェクト・メンバーのみが常に使用され、同じフィールド名を持つ他のメンバーは無視されます。このような複数のメンバーのうちどれが使用されるかは指定されていません。

"JSONオブジェクトの一意フィールドと重複フィールドを参照してください。

関連項目:

39.5.4.1 Oracle SQL関数JSON_VALUEとブール型のJSON値の使用

JSONには、ブール型の値trueおよびfalseがあります。Oracle SQLには、ブール・データ型がありません。Oracle SQLファンクションjson_valueによってOracle JSONパス式が評価され、結果がtrueまたはfalseである場合、結果をSQLで処理する方法は文字列と数値の2通りあります。

デフォルトでは、戻されるデータ型はSQL文字列(VARCHAR2)であり、これは、結果が文字列'true'または'false'であることを意味します。または、結果をSQL数値として戻すこともでき、この場合、JSON値trueは数値1として戻され、false0として戻されます。

例39-7に、これを示します。最初の問合せでは文字列'true'を戻し、2番目の問合せでは数値1を戻します。

注意:

ブール値を数値として戻すことはできますが、このような値はJSONの検索索引の対象となりません。このような理由により、デフォルトの戻り値のデータ型VARCHAR2を使用することをお薦めします。

例39-7 JSON_VALUE: SQLでJSONのブール値を戻す2通りの方法

SELECT json_value(po_document, '$.AllowPartialShipment')
 FROM j_purchaseorder;

SELECT json_value(po_document, '$.AllowPartialShipment' RETURNING NUMBER)
  FROM j_purchaseorder;

39.5.4.2 JSONのnull値に適用されるOracle SQL関数JSON_VALUE

JSON値nullに適用されたOracle SQL関数json_valueは、SQL文字列'null'ではなく、SQLのNULLを戻します。つまり、特に、json_valueを使用してJSON値nullと値が存在しないことの区別はできません。この場合、SQLのNULLは両方の事例を表します。

39.5.4.3 JSON_TABLEとしてのJSON_VALUE

Oracle SQL関数json_valueは、関数json_tableの特別な事例であるとみなすことができます。

例39-8に、この対応を示します。2つのSELECT文で得られる結果は同じになります。

この対応は、おそらくjson_valueについてより深く理解する手助けとなるのみでなく、どちらの関数を使用しても同じ結果が得られることを意味しているため、実質的に重要な意味を持ちます。

特に、json_valueを複数回使用する場合、またはこれをjson_existsまたはjson_query (これらもjson_tableを使用して表すことができます)と組み合せて使用して同じデータにアクセスする場合、json_tableを1回呼び出す方が、データが解析されるのが1回のみであるという利点があります。

このため、オプティマイザがjson_existsjson_valueおよびjson_queryの複数の呼出し(任意の組合せ)を、より少ないjson_tableの呼出しに自動的にリライトすることがよく起こります。

例39-8 JSON_TABLEを使用して表されたJSON_VALUE

SELECT json_value(column, json_path RETURNING data_type error_hander ON ERROR)
  FROM table;

SELECT jt.column_alias
  FROM table,
       json_table(column, '$' error_handler ON ERROR
         COLUMNS ("COLUMN_ALIAS" data_type PATH json_path)) AS "JT";

39.5.5 Oracle SQL関数JSON_QUERY

Oracle SQL関数json_queryは、1つ以上の値をJSONデータから選択し、JSON値を表す文字列(VARCHAR2)を戻します。(関数json_valueとは異なり、戻されるデータ型をNUMBERにすることはできません。)したがって、json_queryを使用してJSON文書のフラグメントを取得できます。

json_queryの最初の引数は、スカラーのSQLデータ型のインスタンスを戻すSQL式です(つまり、オブジェクト・データ型でもコレクション・データ型でもありません)。これは、データ型VARCHAR2BLOBまたはCLOBのいずれかになります。これは、適切にキャストされた表またはビューの列の値、PL/SQL変数、バインド変数のいずれかになります。SQL式の評価の結果は、パス式を評価するためのコンテキスト項目として使用されます。

json_queryの2番目の引数は、Oracle JSONパス式の後ろにオプションのRETURNING句、オプションのラッパー句およびオプションのエラー句が付いた形式です。このパス式は、任意の数のJSON値を対象とすることができます。

RETURNING句で指定できるのはデータ型VARCHAR2のみであり、NUMBERを指定することはできません。

ラッパー句により、戻される文字列値の形式が決まります。

json_queryのエラー句ではEMPTY ON ERRORを指定でき、これは、エラーが発生した場合は空の配列([])が戻されることを意味します。

例39-9は、Oracle SQL関数json_queryとともに配列ラッパーを使用する例を示しています。文書ごとにVARCHAR2値が戻され、この内容は、電話のタイプの要素が不特定の順序で含まれるJSON配列を表します。例39-4の文書では、電話のタイプは"Office"および"Mobile"であり、戻される配列は["Mobile", "Office"]または["Office", "Mobile"]です。

例39-9でパス式$.ShippingInstructions.Phone.typeが使用されていたとしても、同じ結果が得られるはずです。Oracle JSONのパス式構文の緩和のため、[*].type.typeに相当します。

例39-9 JSON_QUERYを使用したJSON値の選択

SELECT json_query(po_document, '$.ShippingInstructions.Phone[*].type'
                               WITH WRAPPER)
  FROM j_purchaseorder;

39.5.5.1 JSON_TABLEとしてのJSON_QUERY

Oracle SQL関数json_queryは、関数json_tableの特別な事例であるとみなすことができます。

例39-10に、この対応を示します。2つのSELECT文で得られる結果は同じになります。

この対応は、おそらくjson_queryについてより深く理解する手助けとなるのみでなく、どちらの関数を使用しても同じ結果が得られることを意味しているため、実質的に重要な意味を持ちます。

特に、json_queryを複数回使用する場合、またはこれをjson_existsまたはjson_value (これらもjson_tableを使用して表すことができます)と組み合せて使用して同じデータにアクセスする場合、json_tableを1回呼び出す方が、データが解析されるのが1回のみであるという利点があります。

このため、オプティマイザがjson_existsjson_valueおよびjson_queryの複数の呼出し(任意の組合せ)を、より少ないjson_tableの呼出しに自動的にリライトすることがよく起こります。

例39-10 JSON_TABLEを使用して表されたJSON_QUERY

SELECT json_query(column, json_path
                  RETURNING data_type array_wrapper error_hander ON ERROR)
  FROM table;

SELECT jt.column_alias
  FROM table,
       json_table(column, '$' error_handler ON ERROR
         COLUMNS ("COLUMN_ALIAS" data_type FORMAT JSON array_wrapper
                  PATH json_path)) AS "JT";

39.5.6 Oracle SQL関数JSON_TABLE

Oracle SQL関数json_tableは、JSONデータをリレーショナル・フォーマットに投影します。json_tableを使用して、JSON式の評価結果を新規の仮想表のリレーショナル行および列に分解しますが、これは、インラインのリレーショナル・ビューであるとみなすこともできます。

この仮想表は、既存のデータベース表に挿入でき、またSQLを使用して(join式など)問合せできます。

特に、json_tableの一般的な使用目的は、JSONデータのリレーショナル・ビューを作成することです。このようなビューは、任意のリレーショナル表またはリレーショナル・ビューを使用する場合と同じように使用できます。このため、アプリケーション、ツールおよびプログラマは、JSONデータをリレーショナルであるかのように、つまり、JSONまたはJSONパス式の構文を考慮せずに操作できます。

JSONデータを介してリレーショナル・ビューを定義することにより、実質的にある種のスキーマがそのデータにマップされます。このマッピングは、事後に行われます。つまり、基礎となるJSONデータは、スキーマまたは特定の使用パターンを考慮せずに定義および作成できます。データが最初で、スキーマが後です。

このようなスキーマ(マッピング)により、基礎となる表に格納できるJSON文書の種類に(整形式のJSONデータであること以外の)制約が課されることはありません。リレーショナル・ビューでは、ビューを定義するマッピング(スキーマ)に準拠するデータのみが公開されます。ビューを再定義するだけでスキーマを変更でき、基礎となるJSONデータを再編成する必要はありません。例39-17は、json_tableを使用したリレーショナル・ビューの作成を示しています。

json_tableはSQLのFROM句で使用します。したがって、これは行ソースです。これにより、行パス式(行パターン)によって選択されたJSON値ごとにリレーショナル・データの行が生成されます。

json_tableの呼出しによって作成される行は、暗黙的にこれらの行の生成元の行に水平結合されます。つまり、json_tableによって生成される仮想表を、JSONデータが含まれる表に明示的に結合する必要はありません。

json_tableの最初の引数は、スカラーのSQLデータ型のインスタンスを戻すSQL式です(つまり、オブジェクト・データ型でもコレクション・データ型でもありません)。これは、データ型VARCHAR2BLOBまたはCLOBのいずれかになります。これは、適切にキャストされた表またはビューの列の値、PL/SQL変数、バインド変数のいずれかになります。SQL式の評価の結果は、行パス式を評価するためのコンテキスト項目として使用されます。

json_tableの2番目の引数は、Oracle JSON行パス式の後ろに、行を処理するためのオプションのエラー句と(必須の) COLUMNS句が付いた形式です。(RETURNING句はありません。)このパス式は、任意の数のJSON値を対象とすることができます。

行パス式は、生成される仮想表の行のパターンとして機能します。これが、SQLのFROM句によって提供されるコンテキスト項目と照合されることにより、COLUMNS句に指定するリレーショナル列に編成されるSQLデータの行が生成されます。これらの各行が0個以上の列パス式と照合され、仮想表のリレーショナル列が生成されます。

json_tableのエラー処理には2つのレベルがありますが、これらは、パス式の2つのレベルである行と列に対応しています。存在する場合、列のエラー・ハンドラにより、行レベルのエラー処理がオーバーライドされます。両レベルのデフォルトのエラー・ハンドラはNULL ON ERRORです。

必須のCOLUMNS句は、json_tableによって作成される仮想表の列を定義します。これは、キーワードCOLUMNSの後ろに次のエントリをカッコで囲んだ形式で構成されます。

  • COLUMNS句内の多くても1つのエントリは、生成される行数の列(SQLデータ型NUMBER)を指定するキーワードFOR ORDINALITYを列名の後ろに付けた形式にすることができます。これらの数は1から始まります。

  • オプションのFOR ORDINALITYエントリ以外、COLUMNS句の各エントリは、標準列指定またはネストした列指定です。

  • 標準列指定は、列名の後ろに、列のオプションのスカラー・データ型(JSON用の他のOracle SQL関数のRETURNING句の場合と同じようにSQLデータ型VARCHAR2またはNUMBERにすることができます)、その後ろにオプションの値句および必須のPATH句が付いた形式で構成されます。デフォルトのデータ型はVARCHAR2(4000)です。

  • ネストした列 は、キーワードNESTEDの後ろにオプションのPATHキーワード、Oracle JSON行パス式、およびCOLUMNS句が付いた形式で構成されます。このCOLUMNS句は、ネストしたデータを表す列を指定します。ここで使用される行パス式により、指定したネストした列のコンテキストが洗練されます。ネストした各列のパス式は行パス式を基準にしたものになります。

    COLUMNS句は(ネストしていてもネストしていなくても)どのレベルでも同じ特性を持ちます。つまり、COLUMNS句は再帰的に定義されます。ネストのレベルごとに(つまり、キーワードNESTEDが使用されるたびに)、ネストしたCOLUMNS句は、ネスト元のCOLUMNS句(その)のと呼ばれます。同じ親句を持つ複数のCOLUMNS句は兄弟です。

    親子のCOLUMNS句によって定義される仮想表は、外部結合を使用して結合されますが、この場合、親が外部表になります。兄弟のCOLUMNS句によって定義される仮想列は、結合を使用して結合されます。

    例39-16は、ネストした列句の使用を示しています。

  • オプションの値句は、列に投影されたデータを処理する方法、つまり、データをjson_valuejson_existsまたはjson_queryと同じように処理するかどうかを指定します。この値処理には、戻りデータ型、戻り形式(prettyまたはASCII)、ラッパー、およびエラーの処理が含まれます。

    デフォルトでは、投影されたデータはjson_valueによって処理されたかのように処理されます。キーワードEXISTSを使用すると、json_existsによって処理されたかのように処理されます。キーワードFORMAT JSONを使用すると、json_queryによって処理されたかのように処理されます。

    FORMAT JSONの場合、明示的なラッパー句を追加することにより、デフォルトのラッパー動作をオーバーライドできます。

    特定のハンドラ(json_valuejson_existsまたはjson_query)のデフォルトのエラー処理を、それに適した明示的なERROR句を追加することでオーバーライドできます。

  • 必須のPATH句は、列の内容として使用される行の部分を指定します。キーワードPATHに続く列パス式は、仮想行によって提供されるコンテキスト項目と照合されます。この列パス式は、行パス式によって指定されるパスに対して相対的であるため、相対パスの表記にする必要があります。

関連項目:

39.5.6.1 JSON_TABLEによる他のOracle SQL関数の汎化

Oracle SQLファンクションjson_tableは、SQL条件json_existsとSQLファンクションjson_valueおよびjson_queryを一般化します。これらの関数を使用して実行できる処理はすべて、json_tableを使用して実行できます。これらによって実行されるジョブについては、これらの関数の構文の方がjson_tableの構文よりも簡単に使用できます。

json_existsjson_valueまたはjson_queryを複数回使用して、またはこれらを組み合せて使用して同じデータにアクセスする場合、json_tableを1回呼び出す方が、データが解析されるのが1回のみであるという利点があります。

このため、オプティマイザがjson_existsjson_valueおよびjson_queryの複数の呼出し(任意の組合せ)を、データの解析が1回だけになるように、より少ないjson_tableの呼出しに自動的にリライトすることがよく起こります。

例39-11および例39-12に、これを示します。これらではそれぞれ、列j_purchaseorder.po_document内の各オブジェクトによって使用される要求者および一連の電話を選択しています。ただし、例39-12では、この列を4回ではなく1回のみ解析しています。

例39-12と関連して次の点に注意してください。

  • JSON値のnullは、SQLに関するかぎりは1つのであり、SQLで値の欠如(存在しないデータ、不明なデータまたは適用できないデータ)を表すNULLとは異なります例39-12で、オブジェクト属性zipCodeのJSON値がnullである場合、SQL文字列'true'が戻されます。

  • json_existsによってブール値が戻されますが、これは、SQL値として、SQL文字列'true'または'false'によって表されます。json_existsがSQLのWHERE句またはCASE文の条件として直接使用される場合、この戻り値を明示的にテストする必要はありません。単にjson_exists(...)と入力してかまいません。ただし、json_existsを得るために他の場所で使用される場合、この値をテストする唯一の方法はこの値を明示的な文字列として使用する方法です。これが例39-12の事例です。値は列jt.has_zipに格納されてから、SQL文字列'true'と等価かどうかが明示的にテストされています。

  • JSONオブジェクト属性AllowPartialShipmentには、JSONのブール値があります。この値にjson_valueが適用される場合、これは文字列または数値として戻される場合があります。例39-12では、json_value暗黙的な使用により、この値はデータ型NUMBERとして戻されてから、数値1と等価かどうかがテストされています。

例39-11 JSONデータに複数回アクセスすることによるデータの抽出

SELECT json_value(po_document, '$.Requestor' RETURNING VARCHAR2(32)),
       json_query(po_document, '$.ShippingInstructions.Phone'
                               RETURNING VARCHAR2(100))
  FROM j_purchaseorder
  WHERE json_exists(po_document, '$.ShippingInstructions.Address.zipCode')
    AND json_value(po_document,  '$.AllowPartialShipment' RETURNING NUMBER(1))
        = 1;

例39-12 JSON_TABLEの使用によって複数回の解析が不要なデータの抽出

SELECT jt.requestor, jt.phones
  FROM j_purchaseorder,
       json_table(po_document, '$'
         COLUMNS (requestor VARCHAR2(32 CHAR) PATH '$.Requestor',
                  phones    VARCHAR2(100 CHAR) FORMAT JSON
                            PATH '$.ShippingInstructions.Phone',
                  partial   NUMBER(1) PATH '$.AllowPartialShipment',
                  has_zip   VARCHAR2(5 CHAR) EXISTS
                            PATH '$.ShippingInstructions.Address.zipCode')) jt
  WHERE jt.partial = 1 AND has_zip = 'true';

39.5.6.2 JSON_TABLEとJSON配列の使用

JSON値は、1つの配列にすることも、1つ以上の配列を含めることも可能であり、他のJSON配列またはオブジェクト内の任意の数のレベルにネストしてもかまいません。json_table NESTEDパス句を使用して、配列の特定の要素を投影できます。

例39-13では、JSONデータ内の要求者および関連する電話番号を列po_document内に投影しています。JSON配列Phone全体がJSONデータph_arrのリレーショナル列として投影されています。このJSONデータをVARCHAR2列としてフォーマットするには、キーワードFORMAT JSONが必要です。

JSON配列Phone全体ではなく、配列の個別要素のみを投影する場合はどうすればよいでしょうか。例39-14は、これを行う方法の1つを示しており、投影する必要があるデータが配列要素のみである場合、この方法を使用できます。

要求者と関連する電話データの両方を投影する場合、例39-14の行パス式($.Phone[*])は適切ではありません。この式は、配列Phoneの(電話オブジェクト)要素のみを対象としています。

例39-15は、両方を対象とする方法の1つを示しています。ここでは、名前と電話配列全体の両方を対象とする行パス式を使用するとともに、個別電話オブジェクトのフィールドtypeおよびnumberを対象とする列パス式を使用しています。

例39-15では例39-13の場合のようにキーワードFORMAT JSONが必要ですが、これは、生成される列VARCHAR2にJSONデータ(つまり、電話ごとに1つの配列要素という形式による電話のタイプまたは電話番号の配列)が含まれるためです。また、例39-13の事例とは異なり、列phone_typeおよびphone_numにラッパー句が必要ですが、これは、フィールドtypeおよびnumberを持つオブジェクトが配列Phoneに複数含まれるためです。

例39-15の結果は、状況によっては求めるものとは異なる場合があります。たとえば、電話番号のJSON配列が含まれるリレーショナル列(特定の発注書のすべての番号に対して1つの行)ではなく、単一の電話番号が含まれるリレーショナル列(番号当たり1つの行)が必要な場合があります。

この場合、配列に対してjson_tableNESTEDパス句を使用することにより、配列要素を投影するようjson_tableに命令を出す必要があります。NESTEDパス句は実質的に、追加の行ソース(行パターン)として機能します。例39-16に、これを示します。

キーワードNESTEDは1回のjson_tableの呼出しで何回でも使用できます。

例39-16では、外部のCOLUMNS句は、ネストした(内部の) COLUMNS句の親です。定義されている仮想表は外部結合を使用して結合されますが、この場合、親句によって定義される表が結合における外部表になります。

(同じ親の下で直接ネストされた2番目の列の句がある場合、これら2つのネストした句は兄弟のCOLUMNS句になります。)

例39-17は、JSONデータを介してリレーショナル・ビューを定義しています。ここでは、NESTEDパス句を使用して配列LineItemsの要素を投影しています。

例39-13 JSON配列全体のJSONデータとしての投影

SELECT jt.*
  FROM j_purchaseorder,
       json_table(po_document, '$'
         COLUMNS (requestor VARCHAR2(32 CHAR) PATH '$.Requestor',
                  ph_arr    VARCHAR2(100 CHAR) FORMAT JSON
                            PATH '$.ShippingInstructions.Phone')) AS "JT";

例39-14 JSON配列の要素の投影

SELECT jt.*
  FROM j_purchaseorder,
       json_table(po_document, '$.ShippingInstructions.Phone[*]'
         COLUMNS (phone_type VARCHAR2(10) PATH '$.type',
                  phone_num  VARCHAR2(20) PATH '$.number')) AS "JT";

PHONE_TYPE     PHONE_NUM
----------     ---------
Office         909-555-7307
Mobile         415-555-1234

例39-15 JSON配列の要素と他のデータの投影

SELECT jt.*
  FROM j_purchaseorder,
       json_table(po_document, '$'
         COLUMNS (
           requestor  VARCHAR2(32 CHAR) PATH '$.Requestor',
           phone_type VARCHAR2(50 CHAR) FORMAT JSON WITH WRAPPER
                      PATH '$.ShippingInstructions.Phone[*].type',
           phone_num  VARCHAR2(50 CHAR) FORMAT JSON WITH WRAPPER
                      PATH '$.ShippingInstructions.Phone[*].number')) AS "JT";

REQUESTOR    PHONE_TYPE            PHONE_NUM
---------    ----------            ---------
Alexis Bull  ["Office", "Mobile"]  ["909-555-7307", "415-555-1234"]

例39-16 JSON_TABLE: NESTEDを使用した配列要素の投影

SELECT jt.*
  FROM j_purchaseorder,
       json_table(po_document, '$'
         COLUMNS (
           requestor VARCHAR2(32 CHAR) PATH '$.Requestor',
           NESTED                      PATH '$.ShippingInstructions.Phone[*]'
             COLUMNS (phone_type VARCHAR2(32 CHAR) PATH '$.type',
                      phone_num  VARCHAR2(20 CHAR) PATH '$.number'))) AS "JT";

例39-17 JSONデータを介したリレーショナル・ビューの定義

CREATE OR REPLACE VIEW j_purchaseorder_detail_view AS
  SELECT d.*
    FROM j_purchaseorder po,
         json_table(po.po_document, '$'
           COLUMNS (
             po_number        NUMBER(10)         PATH '$.PONumber',
             reference        VARCHAR2(30 CHAR)  PATH '$.Reference',
             requestor        VARCHAR2(128 CHAR) PATH '$.Requestor',
             userid           VARCHAR2(10 CHAR)  PATH '$.User',
             costcenter       VARCHAR2(16)       PATH '$.CostCenter',
             ship_to_name     VARCHAR2(20 CHAR)
                              PATH '$.ShippingInstructions.name',
             ship_to_street   VARCHAR2(32 CHAR)
                              PATH '$.ShippingInstructions.Address.street',
             ship_to_city     VARCHAR2(32 CHAR)
                              PATH '$.ShippingInstructions.Address.city',
             ship_to_county   VARCHAR2(32 CHAR)
                              PATH '$.ShippingInstructions.Address.county',
             ship_to_postcode VARCHAR2(10 CHAR)
                              PATH '$.ShippingInstructions.Address.postcode',
             ship_to_state    VARCHAR2(2 CHAR)
                              PATH '$.ShippingInstructions.Address.state',
             ship_to_zip      VARCHAR2(8 CHAR)
                              PATH '$.ShippingInstructions.Address.zipCode',
             ship_to_country  VARCHAR2(32 CHAR)
                              PATH '$.ShippingInstructions.Address.country',
             ship_to_phone    VARCHAR2(24 CHAR)
                              PATH '$.ShippingInstructions.Phone[0].number',
             NESTED PATH '$.LineItems[*]'
               COLUMNS (
                 itemno      NUMBER(38)         PATH '$.ItemNumber', 
                 description VARCHAR2(256 CHAR) PATH '$.Part.Description', 
                 upc_code    VARCHAR2(14 CHAR)  PATH '$.Part.UPCCode', 
                 quantity    NUMBER(12,4)       PATH '$.Quantity', 
                 unitprice   NUMBER(14,2)       PATH '$.Part.UnitPrice'))) d;

39.6 JSONデータに対する単純なドット表記法アクセス

問合せに対しては、より詳細だがより柔軟なOracle SQL関数json_queryおよびjson_valueの使用に代わるものとして、単純なドット表記法構文が用意されています。ドット表記法は、可能な場合は常にJSON値を戻すよう作られています。

Oracle SQL関数json_queryおよびjson_valueは、Oracle JSONパス式を引数として受け入れ、ターゲットのJSONデータと照合します。それらは、戻り値のデータ型、複数の値を配列としてラップするかどうか、およびエラーの処理方法を指定するために、オプションのRETURNING句、ラッパー句、およびエラー処理句をそれぞれ受け入れます。

単純なユースケースに代わる手段として、ドット表記法構文を使用することにより、json_queryまたはjson_valueを使用せずにJSONデータを問い合せることができます。

ドット表記法を使用した問合せの動作は、json_queryjson_valueのどちらとも異なります。実質的に、これらの動作を組み合せて、可能であれば常に1つ以上のJSON値を戻します。

パス式がJSONデータと一致しないためにこれらのSQL関数のどちらかではNULLが戻されたりエラーが発生する可能性がありますが、ドット表記法の問合せでは多くの場合、有用なJSON値が戻されます。戻り値は常に、JSONデータを表す文字列(データ型VARCHAR2)です。文字列の内容は、次のように対象のJSONデータによって決まります。

  • 単一のJSON値が対象である場合、この値はJSONスカラー、オブジェクトまたは配列のいずれであるかに関係なく文字列内容です。

  • 複数のJSON値が対象である場合、文字列の内容は、これらの値が要素であるJSON配列です。

最初の事例における動作は、スカラー値の場合はjson_valueの動作と似ており、オブジェクトまたは配列値の場合はjson_queryの動作と似ています。

2番目の事例における動作は、配列ラッパーを使用したjson_queryの動作と似ています。

ドット表記法の構文は、表の別名(必須)に、ドット(.)、JSON列の名前および. json_keyまたは. json_keyarray_stepを続けたものの形式をした1つ以上のペアです。ここでjson_keyはJSONキーで、array_stepは、「Oracle JSONパス式の基本的な構文」で説明されている配列ステップ式です。

json_keyは有効なSQL識別子である必要があり、列にはis jsonチェック制約が設定されている必要があり、これにより、整形式のJSONデータが含まれるようにします。これらの規則のどちらも順守されない場合、問合せのコンパイル時にエラーが発生します。(エラーの発生を回避するには、チェック制約が存在する必要があります。ただし、これは、アクティブである必要はありません。制約を非アクティブ化すると、このエラーは発生しません。)

このJSONドット表記法の場合、SQLの一般的な事例とは異なり、引用符で囲まれていない識別子(列名の後ろ)は、大文字と小文字を区別して(つまり、引用符で囲まれているかのように)処理されます。これは大変都合がよく、JSONキーを引用符で囲まなくても識別子として使用できます。たとえば、jcolumn."friends"ではなく、jcolumn.friendsと入力してかまいません。また、JSONオブジェクトが大文字を使用して名前を付けられている場合(FRIENDSなど)、jcolumn.friendsではなくjcolumn.FRIENDSと書く必要があります。

次に、ドット表記法構文の例をいくつか示します。すべて、poという別名を持つ表のJSON列po_documentを参照しています。

  • po.po_document.PONumber – キーPONumberの値。

  • po.po_document.LineItems[1] – 配列LineItemsの2つ目の要素(配列の位置は0が基準)。

  • po.po_document.LineItems[*] – 配列LineItemsのすべての要素(*はワイルドカード)。

  • po.po_document.ShippingInstructions.name – オブジェクトShippingInstructionsの子であるキーnameの値。

注意:

  • ドット表記法構文の各コンポーネントは最大30バイトに制限されています。

    SQLドット表記法構文およびSQL識別子の詳細は、Oracle Database SQL言語リファレンスを参照してください。

  • 単純なドット表記法のJSON問合せでは、4Kバイトよりも長い値は戻せません。値がこの制限を超えると、かわりにSQL NULLが戻されます。実際の値を取得するには、記法にドットを付けず、通常の問合せ構文を使用します。つまり、Oracle SQL関数json_queryまたはjson_valueを使用して、RETURNING句で適切な戻り型を指定します。

    JSONドット表記法構文の詳細は、Oracle Database SQL言語リファレンスを参照してください。

JSONデータに対するJSONドット表記法の式の照合は、Oracle JSONパス式の場合と同じであり、これには、暗黙の配列反復を許可する緩和が含まれます(「Oracle JSONパス式の構文の緩和」を参照)。ドット表記法の式のJSON列はパス式のコンテキスト項目に相当し、ドット表記法で使用される各識別子は、パス式で使用される各識別子に相当します。

たとえば、JSON列jcolumnがパス式のコンテキスト項目に相当する場合、ドット表記法の式jcolumn.friends$.friendsに相当し、jcolumn.friends.name$.friends.nameに相当します。

後者の場合、コンテキスト項目はオブジェクトでもオブジェクトの配列でもかまいません。これがオブジェクトの配列である場合、各オブジェクトはキーfriendsに対して照合されます。キーfriendsの値自体はオブジェクトでもオブジェクトの配列でもかまいません。後者の場合、配列内の最初のオブジェクトが使用されます。

配列要素に対してワイルドカードを暗黙で使用する場合(「Oracle JSONパス式の構文の緩和」を参照)以外では、ワイルドカードを使用したパス式をドット表記法構文を使用して表すことはできません。ドット表記法構文は、単純なパス式の使用に対する便利な代替手段ですが、一般的なパス式の使用の代用手段ではありません。

例39-18は、ドット表記法の問合せとjson_valueの問合せの対応を示しています。例39-4のデータが与えられた場合、各問合せにより、文字列"1600" (JSON数値1600を表す値VARCHAR2)が戻されます。

例39-19は、ドット表記法の問合せとjson_queryの問合せの対応を示しています。最初のペアの各問合せにより、電話オブジェクトのJSON配列(を表す値VARCHAR2)が戻されます。2番目のペアの各問合せにより、例39-9の場合のように、電話のタイプの配列(を表す値VARCHAR2)が戻されます。

関連項目:

例39-18 JSONドット表記法の問合せとJSON_VALUEの比較

SELECT po.po_document.PONumber FROM j_purchaseorder po;

SELECT json_value(po_document, '$.PONumber') FROM j_purchaseorder;

例39-19 JSONドット表記法の問合せとJSON_QUERYの比較

SELECT po.po_document.ShippingInstructions.Phone FROM j_purchaseorder po;

SELECT json_query(po_document, '$.ShippingInstructions.Phone')
  FROM j_purchaseorder;

SELECT po.po_document.ShippingInstructions.Phone.type FROM j_purchaseorder po;

SELECT json_query(po_document, '$.ShippingInstructions.Phone.type' WITH WRAPPER)
  FROM j_purchaseorder;

39.7 JSONデータの索引

JSONデータには、これを格納するために使用する任意のデータ型の場合と同じように索引を付けることができます。また、JSON検索索引を定義できます。これは、非定型の構造的問合せと全文問合せの両方に便利です。

39.7.1 JSONデータに対して関数ベースの索引が選択されるかどうかを確認する方法

特定の問合せで特定の関数ベースの索引が選択されるかどうかを確認するには、問合せの実行計画内で索引名を検索します。

たとえば、例39-22で定義されている索引が指定された場合、例39-18json_value問合せの実行計画では索引po_num_id1を使用して索引スキャンが参照されます。

39.7.2 Oracle SQL条件JSON_EXISTSのビットマップ索引の作成

json_existsで戻される値に対して、ビットマップ索引を作成できます。条件に対して想定される戻り値が2つ(trueおよびfalse)のみであるため、これはjson_existsでの使用に適した索引です。

これを、例39-20に示します。

例39-21では、json_valueによって戻される値のビットマップ索引を作成しています。データ内のフィールドCostCenterに対して想定される値が少ない場合、これは使用に適した索引です。

例39-20 JSON_EXISTSのビットマップ索引の作成

CREATE BITMAP INDEX has_zipcode_idx
  ON j_purchaseorder (json_exists(po_document, 
                                  '$.ShippingInstructions.Address.zipCode'));

例39-21 JSON_VALUEのビットマップ索引の作成

CREATE BITMAP INDEX cost_ctr_idx
  ON j_purchaseorder (json_value(po_document, '$.CostCenter'));

39.7.3 JSON_VALUE関数ベースの索引の作成

SQLファンクションjson_valueに対して関数ベースの索引を作成できます。これには標準の構文を使用(json_value)するか、単純なドット表記法構文を使用できます。これらいずれかの方法で作成された索引は、ドット表記法問合せとjson_value問合せのどちらとも一緒に使用できます。

例39-22では、表j_purchaseorderの列po_document内にあるオブジェクトのフィールドPONumberに対するjson_valueの関数ベースの索引を作成しています。オブジェクトはパス式のコンテキスト項目として渡されます。

ここでERROR ON ERRORを使用することは、フィールドPONumberないレコード、または非数値の値を持つフィールドPONumberがあるレコードがデータに含まれる場合、索引の作成が失敗することを意味します。また、索引が存在する場合、このようなレコードを挿入しようとしても失敗します。

代替方法として、「JSONデータに対する単純なドット表記法アクセス」で説明されている簡単な構文を使用して索引を作成する方法があります。例39-23はこれを示しています。ここでは、ドット表記法の問合せで戻すことが可能な内容に応じてスカラー結果と非スカラー結果の両方に索引を付けています。

例39-22例39-23の両方で作成された索引は、ドット表記法構文を使用する問合せとjson_valueを使用する問合せのいずれかに対して選択できます。

例39-23の索引が問合せjson_valueに対して選択される場合、正しいフィールド値をテストするために、索引の選択後にフィルタリングが適用されます。この索引には非スカラー値を格納でき、ドット表記法の問合せではこのような値を戻すことができますが、json_valueの問合せではできないため、このような値は索引選択後にフィルタで除外されます。

次のいずれかの形式を使用してjson_valueに対して関数ベースの索引を作成することをお薦めします。

  • RETURNINGデータ型を指定し、ERROR ON ERRORを使用するjson_value

    索引が付けられる値は、指定したデータ型の(非nullの)スカラー値のみです。それでもなお、索引は、このようなスカラー結果が生成されるドット表記法問合せで使用できます。

  • ドット表記法構文

    索引が付けられる値は、可能な場合は常にJSON値を戻すドット表記法問合せの柔軟な動作に対応します。これには、非スカラーのJSON値(JSONオブジェクトおよび配列)が含まれる場合があります。これらは、json_valueの問合せに加えてドット表記法の問合せと照合できます。索引は、初期セットの一致結果を見つけ出すために使用され、これらの一致結果は問合せの詳細事項に応じてフィルタされます。たとえば、索引が付けられた値のうちJSONスカラーでないものはフィルタで除外されます。

このように、これらいずれかの方法で作成された索引は、ドット表記法問合せとjson_value問合せのどちらとも一緒に使用できます。

例39-22 JSONオブジェクト・フィールドに対する関数ベースの索引の作成: JSON_VALUE

CREATE UNIQUE INDEX po_num_idx1
  ON j_purchaseorder (json_value(po_document, '$.PONumber' 
                                 RETURNING NUMBER ERROR ON ERROR));

例39-23 JSONオブジェクト・フィールドに対する関数ベースの索引の作成: ドット表記法

CREATE UNIQUE INDEX po_num_idx2 ON j_purchaseorder po (po.po_document.PONumber);

39.7.4 JSON_VALUE関数ベースの索引とJSON_TABLE問合せの使用

json_tableによって投影された列をWHERE句が参照し、この列を対象とする有効なJSONパスが索引付きパス式と一致する場合、json_tableが関連する問合せに対して、ERROR ON ERRORが設定されたjson_value,を使用して作成された索引を使用できます。

この索引が索引付きパスに対する制約として機能することにより、JSONコレクション内の各項目に対して1つの(非nullの)スカラーのJSON値のみが確実に投影されるようになります。

したがって、例39-24の問合せでは、例39-22で作成された索引を使用しています。

注意:

json_value式またはドット表記法を使用して作成された関数ベースの索引を、問合せのWHERE句内で対応する存在に対して選択できるのは、この存在がSQLの比較式(>=など)で使用されている場合のみです。特に、これは、条件IS NULLまたはIS NOT NULLで使用される存在としては選択されません。

SQL比較条件の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

例39-24 JSON_VALUE関数ベースの索引とJSON_TABLE問合せの使用

SELECT jt.*
  FROM j_purchaseorder po,
       json_table(po.po_document, '$'
         COLUMNS po_number  NUMBER(5) PATH '$.PONumber',
                 reference  VARCHAR2(30 CHAR) PATH '$.Reference',
                 requestor  VARCHAR2(32 CHAR) PATH '$.Requestor',
                 userid     VARCHAR2(10 CHAR) PATH '$.User',
                 costcenter VARCHAR2(16 CHAR) PATH '$.CostCenter') jt
  WHERE po_number = 1600;

39.7.5 JSON_VALUEの索引付けおよび問合せに関するデータ型の考慮事項

デフォルトでは、JSON用のOracle SQL関数ではVARCHAR2値が戻されます。json_valueを使用して関数ベースの索引を作成する場合、RETURNING句を使用して異なる戻りデータ型を指定しないかぎり、非VARCHAR2値を想定する問合せに対してこの索引は選択されません。

たとえば、例39-25の問合せの場合、json_valueRETURNING NUMBERが使用されています。この問合せには例39-22で作成された索引を選択できますが、これは、索引が付けられたjson_value式で戻り型としてNUMBERが指定されているためです。

ただし、例39-23で作成された索引にはRETURNING NUMBER (デフォルトでは、戻り型はVARCHAR2(4000)です)が使用されていないため、このような問合せに対して選択することはできません。

ここで、戻される値の型がVARCHAR2になるようにRETURNING句なしでjson_valueを使用している例39-26例39-27の問合せについて検討してみます。

例39-26では、SQL関数to_numberにより、json_valueによって戻されるVARCHAR2値を数値に明示的に変換しています。同様に、例39-27では、比較条件> (より大きい)により、値を数値に暗黙的に変換しています。

例39-22例39-23の索引のいずれも、これらの問合せに対して選択されません。これらの問合せでは、いずれの事例でも型キャストのために正しい結果が戻される可能性がありますが、これらの索引を使用してこれらの問合せを評価することはできません。

また、一部のデータを特定のデータ型に変換できない場合に何が起きるかについても検討してください。たとえば、例39-25例39-26および例39-27の問合せが実行された場合、"alpha"などのPONumber値はどうなるでしょうか。

例39-26および例39-27の場合、値を数値にキャストしようとするために問合せはエラーで停止します。ただし、例39-25の場合、デフォルトのエラー処理動作がNULL ON ERRORであるため、非数値"alpha"は単純にフィルタで除外されます。値には索引が付けられますが、問合せに対しては無視されます。

同様に、たとえばDEFAULT '1000' ON ERRORが問合せで使用されたとすると、つまり、数値のデフォルト値が指定されたとすると、値"alpha"に対してエラーは発生しません。この場合、デフォルト値の1000が使用されます。

例39-25 JSON_VALUE問合せと明示的なRETURNING NUMBER

SELECT count(*) FROM j_purchaseorder po  WHERE json_value(po_document, '$.PONumber' RETURNING NUMBER) > 1500;

例39-26 JSON_VALUE問合せと明示的な数値変換

SELECT count(*) FROM j_purchaseorder po  WHERE to_number(json_value(po_document, '$.PONumber')) > 1500;

例39-27 JSON_VALUE問合せと暗黙的な数値変換

SELECT count(*) FROM j_purchaseorder po  WHERE json_value(po_document, '$.PONumber') > 1500;

39.7.6 コンポジットBツリー索引を使用した複数のJSONフィールドの索引付け

JSONオブジェクトの複数のフィールドに索引を付けるには、最初にこれらの仮想列を作成します。次に、仮想列に対してコンポジットBツリー索引を作成します。

例39-28および例39-29に、これを示します。例39-28では、JSONオブジェクト・フィールドUserおよびCostCenterそれぞれに対して仮想列useridおよびcostcenterを作成しています。

例39-29では、例39-28の仮想列に対してコンポジットBツリー索引を作成しています。

仮想列または対応するJSONデータ(オブジェクト・フィールド)を参照するSQL問合せでは、コンポジット索引が選択されます。このことは、例39-30の両方の問合せに当てはまります。

これら2つの問合せの効果は同一であり、パフォーマンスも同一です。ただし、最初の問合せ形式はJSONデータ自体を対象としておらず、このデータに索引を付けるために使用される仮想列を対象としています。

問合せのパフォーマンスを向上させるために実装された索引にデータが論理的に依存することはありません。実装からのこのような独立性がコードに反映されるようにするには、2番目の問合せ形式を使用してください。このようにすることにより、問合せは索引の有無とは関係なく同じ機能を果たすようになります。この場合、索引はパフォーマンスの向上に特化して機能します。

例39-28 JSONオブジェクト・フィールドの仮想列の作成

ALTER TABLE j_purchaseorder ADD (userid VARCHAR2(20)
  GENERATED ALWAYS AS (json_value(po_document, '$.User' RETURNING VARCHAR2(20))));

ALTER TABLE j_purchaseorder ADD (costcenter VARCHAR2(6)
  GENERATED ALWAYS AS (json_value(po_document, '$.CostCenter'
                       RETURNING VARCHAR2(6))));

例39-29 JSONオブジェクト・フィールドのコンポジットBツリー索引の作成

CREATE INDEX user_cost_ctr_idx on j_purchaseorder(userid, costcenter);

例39-30 コンポジット索引を使用して索引が付けられたJSONデータを問い合せる2通りの方法

SELECT po_document FROM j_purchaseorder WHERE userid      = 'ABULL'
                                          AND costcenter  = 'A50';

SELECT po_document
  FROM j_purchaseorder WHERE json_value(po_document, '$.User')       = 'ABULL'
                         AND json_value(po_document, '$.CostCenter') = 'A50';

39.8 JSONデータの全文検索

SELECT文のCASE式またはWHERE句でOracle SQL条件json_textcontainsを使用して、VARCHAR2BLOBまたはCLOB列に格納されているJSONデータの全文検索を実行できます。

条件json_textcontainsを使用するには、JSONデータでの使用に特化して設計されたOracle Text索引であるJSON検索索引を最初に作成する必要があります。そうしない場合、json_textcontainsを使用するとエラーが発生します。

JSON検索索引はJSONデータの一般的な非定型問合せに適しており、これらの問合せで全文検索が使用されるかどうかとは関係ありません。

注意:

JSON検索索引は、データベースのキャラクタ・セットがAL32UTF8である場合のみ、およびVARCHAR2BLOBまたはCLOB記憶域を使用するJSONデータの場合のみサポートされます。そうでない場合、索引作成時にエラーが発生します。

JSON検索索引を作成するには、索引型のCTXSYS.CONTEXTおよびセクション・グループCTXSYS.JSON_SECTION_GROUPPARAMETERS句を使用して指定します。例39-31に、これを示します。

例39-32は、明細項目の部品の説明にキーワードMagicが含まれる発注書を検索する全文問合せを示しています。

例39-33は、で作成したJSON検索索引も使用するJSONデータの全文問合せを示しています

注意:

json_valueが使用される場合、JSON検索索引が処理後のフィルタとして使用されます。この索引は、戻り値がNUMBERではなくVARCHAR2である場合のみjson_valueに対して選択でき、等価性比較の場合のみ選択できます。たとえば、これは、json_value(column, '$.name_first') > 'Nimrod'などの比較に対しては選択されません。

問合せの実行計画内にJSON検索索引の名前が存在する場合、索引が実際に問合せに対して選択されたことがわかります。例39-34に示すものと似た行が表示されます。

JSON検索索引は、要求に応じて非同期にメンテナンスされます。したがって、索引メンテナンスのコストを遅延し、コミット時のみまたはデータベースの負荷が軽減されている特定の時期に実行できます。これにより、DMLのパフォーマンスを向上させることができます。また、索引の同期化を行う際に、非同期索引行のバルク・ロードを有効にすると、索引メンテナンスのパフォーマンスを向上させることができます。一方、索引の非同期メンテナンスとは、索引が同期化されるまでは、変更されたか新しく挿入されたデータに索引が使用されないことを意味します。

関連項目:

  • JSONデータを索引付けする別の方法の詳細は、JSONデータの索引を参照してください。

  • 条件json_textcontainsの詳細は、Oracle Database SQL言語リファレンスを参照してください。

  • CTXSYS.CONTEXT索引の詳細は、『Oracle Textリファレンス』を参照してください。

  • セクション・グループCTXSYS.JSON_SECTION_GROUPの詳細は、『Oracle Textリファレンス』を参照してください。

  • JSON検索索引の同期化の詳細は、Oracle Textリファレンスを参照してください。

例39-31 JSON検索索引の作成

CREATE INDEX po_search_idx ON j_purchaseorder (po_document)
  INDEXTYPE IS CTXSYS.CONTEXT
  PARAMETERS ('section group CTXSYS.JSON_SECTION_GROUP SYNC (ON COMMIT)');

例39-32 JSONデータの全文問合せ

SELECT po_document FROM j_purchaseorder
  WHERE json_textcontains(po_document, '$.LineItems.Part.Description', 'Magic');

例39-33 JSONデータの非定型問合せ

SELECT po_document FROM j_purchaseorder
  WHERE json_exists(po_document, '$.ShippingInstructions.Address.country');

SELECT po_document FROM j_purchaseorder
  WHERE json_value(po_document, '$.User') = 'ABULL';

例39-34 JSON検索索引が使用されていることを示す実行計画

|* 2|   DOMAIN INDEX     | PO_SEARCH_IDX |     |     |     4 (0)

39.9 外部JSONデータのロード

JSONデータのデータベース表を、JSONダンプ・ファイルの内容から作成できます。

例39-3および例39-4では、説明を目的として、表j_purchaseorderを作成し、この表にJSONデータの単一行を挿入しています。この項では、JSONダンプ・ファイル$ORACLE_HOME/demo/schema/order_entry/PurchaseOrders.dmp内のデータから全表を作成する方法について説明します。このファイルの形式には、Oracle NoSQL Databaseなどの一般的なNoSQLデータベースによって作成されるエクスポート形式との互換性があります。ファイルの各行には、JSONオブジェクトとして表される単一のJSON文書が含まれます。

例39-35では、ファイルシステム・ディレクトリ$ORACLE_HOME/demo/schema/order_entryに対応するデータベース・ディレクトリを作成しています。次に、例39-37では、このデータベース・ディレクトリを使用して外部表であるjson_dump_file_contentsを作成し、ダンプ・ファイルPurchaseOrders.dmpのデータを入力しています。

例39-38では、外部表json_dump_file_contentsからリレーショナル表j_purchaseorderの列json_documentにJSON文書をコピーしています。

関連項目:

  • 外部表の概要は、『Oracle Database概要』を参照してください。

  • 外部表の詳細は、『Oracle Databaseユーティリティ』を参照してください。

例39-35 データベース・ディレクトリ・オブジェクトの作成

CREATE OR REPLACE DIRECTORY order_entry_dir
  AS '$ORACLE_HOME/demo/schema/order_entry';

例39-36 データベース・ディレクトリ・オブジェクトの作成

CREATE OR REPLACE DIRECTORY loader_output_dir AS '/tmp';Foot 7

例39-37 外部表の作成およびJSONダンプ・ファイルからの入力

CREATE TABLE json_dump_file_contents (json_document CLOB)
  ORGANIZATION EXTERNAL (TYPE ORACLE_LOADER DEFAULT DIRECTORY order_entry_dir
                         ACCESS PARAMETERS
                           (RECORDS DELIMITED BY 0x'0A'
                            DISABLE_DIRECTORY_LINK_CHECK
                            BADFILE loader_output_dir: 'JSONDumpFile.bad'
                            LOGFILE order_entry_dir: 'JSONDumpFile.log'
                            FIELDS (json_document CHAR(5000)))
                         LOCATION (order_entry_dir:'PurchaseOrders.dmp'))
  PARALLEL
  REJECT LIMIT UNLIMITED;

例39-38 外部表からリレーショナル表へのJSONデータのコピー

INSERT INTO j_purchaseorder
  SELECT SYS_GUID(), SYSTIMESTAMP, json_document FROM json_dump_file_contents
    WHERE json_document IS JSON;

39.10 JSONデータのレプリケーション

Oracle GoldenGateを使用して、JSONデータが格納された列を持つ表をレプリケートできます。

Oracle GoldenGateでは、レプリケートする表に非仮想主キー列が必要であることに注意してください。主キー列を仮想にすることはできません。

JSONデータ上のすべての索引もレプリケートされます。ただし、レプリカ・データベース上で、JSON検索索引をメンテナンスするために使用する任意のOracle Text操作を実行する必要があります。このようなプロシージャの例は、次のとおりです。

  • CTX_DDL.create_section_group

  • CTX_DDL.drop_section_group

  • CTX_DDL.set_sec_grp_attr

  • CTX_DDL.sync_index

  • CTX_DDL.optimize_index

関連項目:

Oracle GoldenGateの詳細は、Oracle GoldenGateのドキュメントを参照してください

39.11 JSONに対するOracle Databaseのサポート

JavaScript Object Notation (JSON)に対するOracle Databaseのサポートは、リレーショナル記憶域の使用範囲とJSONデータの問合せの使用範囲のベスト・フィットを実現することにより、リレーショナル問合せとJSON問合せを互いに連携して機能させることを目指しています。

注意:

Oracleは、SQL/JSON標準の一部としてJSONデータへのSQLアクセスに関する標準化に積極的に取り組んでいます。JSONに対するOracle Databaseのサポートは、引き続きこのような標準の開発を追跡し、これとともに進化していきます。



脚注の凡例

脚注1:

JSONはこの点においてJavaScriptとは表記法が異なります。JSONでは、文字列内でエスケープされていないUnicode文字U+2028 (LINE SEPARATOR)およびU+2029 (PARAGRAPH SEPARATOR)が許可されます。JavaScriptの表記法では、文字列内でこのような制御文字をエスケープする必要があります。JSONP (JSON with padding)データを生成するときにこの違いが重要になる場合があります。


脚注2:

したがって、JavaScriptオブジェクトは、CおよびC++のハッシュ表、JavaのHashMap、PHPの連想配列、Pythonのディクショナリ、PerlおよびRubyのハッシュと似ています。


脚注3:

コンストラクタObjectまたはオブジェクト・リテラル構文{...}を使用してJavaScriptでオブジェクトが作成されます。


脚注4: 一部のコンテキストでは、空のフィールド名はOracle Databaseと一緒には使用できません。使用する場合は必ず、名前を二重引用符で囲む必要があります
脚注5:

チェック制約によって論理条件ORを使用して条件is jsonが別の条件と結合される場合、列はこれらのビューにリストされません。この場合、列内のデータがJSONデータであるかどうかは確実ではありません。たとえば、制約jcol is json OR length(jcol) < 1000の場合、列jcol内のデータがJSONデータであることは確認されません


脚注6: オブジェクト・フィールドは、オブジェクトの「キー」と呼ばれることもあります。
脚注7:

この例では、一時ファイルシステム・ディレクトリを使用します。UNIXシステムおよびLinuxシステムでは、これは通常、/tmpです。MS Windowsでは、これは通常、フォルダtemp (c:\tempなど)です。