3 SODA for PL/SQLの使用

SODA for PL/SQLにアクセスする方法と、これを使用してコレクションに対する作成、読取り(取得)および削除(CRUD)操作を実行する方法について説明します。

(CRUD操作は、このドキュメントでは読取りおよび書込み操作とも呼ばれています。)

3.1 SODA for PL/SQLのスタート・ガイド

SODA for PL/SQLにアクセスする方法と、これを使用してデータベース・コレクションを作成し、コレクションにドキュメントを挿入し、コレクションからドキュメントを取得する方法について説明します。

ノート:

このトピック内の一部が初見で理解できないことがあっても問題ありません。必要な概念は、別のトピックで詳しくわかるようになっています。このトピックでは、SODAの使用に関する全体的な関連性について説明しています。

SODA for PL/SQLを開始するステップは次のとおりです。

  1. SODA for PL/SQLを使用する際の前提条件が満たされていることを確認します。「SODA for PL/SQLの前提条件」を参照してください。

  2. コレクションの格納に使用するデータベース・スキーマ(ユーザー・アカウント)を特定し、データベース・ロールSODA_APPをそのスキーマに付与します。

    GRANT SODA_APP TO schemaName;
    
  3. 例3-1に示したようなPL/SQLコードを使用して、次の操作を実行します。

    1. デフォルトのコレクション構成(メタデータ)を使用して、コレクション(PL/SQLオブジェクト・タイプSODA_COLLECTION_Tのインスタンス)を作成して開きます。

    2. PL/SQLオブジェクト・タイプSODA_DOCUMENT_Tのインスタンスとして、特定のJSONコンテンでドキュメントを作成します。

    3. ドキュメントをコレクションに挿入します。

    4. 挿入したドキュメントを取り出します。その他のコンポーネント(コンテンツ以外)は、自動的に生成されます。

    5. 一意のドキュメント・キーを出力します。このキーは、自動的に生成されるコンポーネントの1つです。

    6. ドキュメントの挿入をコミットします。

    7. キーを指定して、コレクション内のドキュメントを検索します。

    8. いくつかのドキュメント・コンポーネント(キー、コンテンツ、コンテンツ作成時のタイムスタンプ、最終変更時のタイムスタンプおよびバージョン)を出力します。

  4. コレクションを削除して、そのコレクションとコレクションのメタデータを保存するために使用していたデータベース表をクリーン・アップします。

    SELECT DBMS_SODA.drop_collection('myCollectionName') AS drop_status FROM DUAL;

    警告:

    SQLを使用して、コレクションの基礎になっているデータベースを削除しないでくださいコレクションを削除することは、そのデータベース表を削除することで終わりにはなりません。表に格納されるドキュメント以外にも、コレクションにはOracle Databaseに永続化されるメタデータも含まれています。コレクションの基礎になっている表を削除しても、コレクション・メタデータは削除されません

ノート:

  • ユーザーが作成したPL/SQLサブプログラムからDBMS_SODAパッケージ内のサブプログラムを呼び出す場合や、サブプログラムに定義者(所有者)権限がある場合、サブプログラムにはロールSODA_APPが付与されている必要があります。たとえば、次のコードでは、所有者がデータベース・スキーマ(ユーザー) my_db_schemaのプロシージャmy_soda_procにロールSODA_APPを付与します。

    GRANT SODA_APP TO PROCEDURE my_db_schema.my_soda_proc;
  • DBMS_SODAサブプログラムは、呼出し元の権限で実行されます。呼出し元は必要な権限を持っている必要があります。たとえば、プロシージャcreate_collectionには権限CREATE TABLEが必要です。(コレクションをバックアップする表を作成する必要があります。)

    通常、このような権限は、直接またはデータベース・ロールを介して呼出し元に付与できます。ただし、定義者の権限で作成されたサブプログラムがDBMS_SODAサブプログラムを呼び出す場合、関連する権限は、その定義者権限サブプログラムを定義したユーザーに対して、ロールを介してではなく、直接付与する必要があります。

関連項目:

ロールSODA_APPの詳細は、『Oracle Databaseセキュリティ・ガイド』Oracle Databaseインストールの事前定義済ロールに関する項を参照してください

例3-1 最初の演習

DECLARE
    collection      SODA_COLLECTION_T;
    document        SODA_DOCUMENT_T;
    foundDocument   SODA_DOCUMENT_T;
    result_document SODA_DOCUMENT_T;
    docKey          VARCHAR2(100);
    status          NUMBER;
BEGIN
    -- Create a collection.
    collection := DBMS_SODA.create_collection('myCollectionName');

    -- The default collection has BLOB content, so create a BLOB-based document.
    document := SODA_DOCUMENT_T(
                  b_content => utl_raw.cast_to_raw('{"name" : "Alexander"}'));

    -- Insert the document and get it back.
    result_document := collection.insert_one_and_get(document);

    -- The result document has auto-generated components, such as key and version,
    -- in addition to the content.  Print the auto-generated document key.
    docKey := result_document.get_key;
    DBMS_OUTPUT.put_line('Auto-generated key is ' || docKey);

    -- Commit the insert
    COMMIT;

    -- Find the document in the collection by its key
    foundDocument := collection.find_one(docKey);

    -- Get and print some document components: key, content, etc.
    DBMS_OUTPUT.put_line('Document components:');
    DBMS_OUTPUT.put_line('  Key: ' || foundDocument.get_key);
    DBMS_OUTPUT.put_line('  Content: '
                         || utl_raw.cast_to_varchar2(foundDocument.get_blob));
    DBMS_OUTPUT.put_line('  Creation timestamp: ' || foundDocument.get_created_on);
    DBMS_OUTPUT.put_line('  Last-modified timestamp: '
                         || foundDocument.get_last_modified);
    DBMS_OUTPUT.put_line('  Version: ' || foundDocument.get_version);
END;
/

例3-2 最初の演習の出力例

例3-1の結果は、次のように出力されます。自動生成されたコンポーネントの値は、実際の実行では異なります。

Auto-generated key is 96F35328CD3B4F96BF3CD01BCE9EBDF5
Document components:
  Key: 96F35328CD3B4F96BF3CD01BCE9EBDF5
  Content: {"name" : "Alexander"}
  Creation timestamp: 2017-09-19T01:05:06.160289Z
  Last-modified timestamp: 2017-09-19T01:05:06.160289Z
  Version: FD69FB6ACE73FA735EC7922CA4A02DDE0690462583F9EA2AF754D7E342B3EE78

3.2 SODA for PL/SQLによるドキュメント・コレクションの作成

PL/SQLファンクションDBMS_SODA.create_collectionを使用すると、デフォルトのメタデータでドキュメント・コレクションを作成できます。

例3-3は、PL/SQLファンクションDBMS_SODA.create_collectionを使用して、デフォルトのメタデータを含むコレクションを作成します。

デフォルトのコレクション・メタデータには次の特性があります。

  • コレクション内の各ドキュメントには次のドキュメント・コンポーネントがあります。

    • キー(Key)

    • コンテンツ(Content)

    • 作成時のタイムスタンプ(Creation timestamp)

    • 最終変更時のタイムスタンプ(Last-modified timestamp)

    • バージョン(Version)

  • コレクションはJSONドキュメントのみを格納できます。

  • ドキュメント・キーは、コレクションに追加したドキュメントに自動的に生成されます。

ほとんどの場合、デフォルトのコレクション構成をお薦めしますが、コレクションは高度な構成が可能です。コレクションを作成する場合、次のような項目を指定できます。

  • 記憶域の詳細。たとえば、コレクションを格納する表の名前、列の名前とデータ型など。

  • 作成時のタイムスタンプ、最終変更のタイムスタンプおよびバージョン用の列の有無。

  • コレクションがJSONドキュメントのみを格納できるかどうか。

  • ドキュメント・キーの生成方式、およびドキュメント・キーをクライアントで割り当てるかまたは自動的に生成するか。

  • バージョンの生成方式。

このように構成できるため、新しいコレクションを既存の表にマップすることもできます。

デフォルト以外の方法でコレクションを構成するには、DBMS_SODA.create_collectionへの2番目の引数として、JSON表現のカスタム・コレクション・メタデータを指定します。

コレクション構成の詳細を問わない場合は、DBMS_SODA.create_collectionにコレクション名のみを渡します(2番目の引数は渡しません)。これにより、デフォルトの構成でコレクションを作成します。

すでに同じ名前のコレクションが存在する場合は、そのコレクションが開かれ、そのハンドルが返されます。カスタム・メタデータが指定されていて、そのメタデータが既存のコレクションのメタデータと一致しない場合、コレクションは開かれずにエラーが発生します。(一致するには、すべてのメタデータ・フィールドが同じ値を保持している必要があります)。

ノート:

特に記載のないかぎり、このドキュメントでは、コレクションはデフォルト構成を使用していると想定しています。

関連項目:

  • コレクション表のデフォルトのネーミングの詳細は、『Oracle Database Simple Oracle Document Access (SODA)の概要』コレクション表のデフォルト・ネーミングに関する項を参照してください

  • PL/SQLファンクションDBMS_SODA.create_collectionの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』CREATE_COLLECTIONファンクションに関する項を参照してください

例3-3 デフォルト・メタデータが含まれるコレクションの作成

この例では、デフォルト・メタデータでmyCollectionNameを作成します。

DECLARE
    collection  SODA_Collection_T;
BEGIN
    collection := DBMS_SODA.create_collection('myCollectionName');   
END;
/

3.3 SODA for PL/SQLによる既存のドキュメント・コレクションのオープン

PL/SQLファンクションDBMS_SODA.open_collectionを使用すると、既存のドキュメント・コレクションをオープンできます。

関連項目:

PL/SQLファンクションDBMS_SODA.open_collectionの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』OPEN_COLLECTIONファンクションに関する項を参照してください

例3-4 既存のドキュメント・コレクションのオープン

この例では、PL/SQLファンクションDBMS_SODA.open_collectionを使用して、myCollectionNameという名前のコレクションをオープンし、このコレクションを表すSODA_COLLECTION_Tインスタンスを返します。NULL値が返された場合、myCollectionNameという名前のコレクションは存在しません。

DECLARE
    collection  SODA_COLLECTION_T;
BEGIN
    collection := DBMS_SODA.open_collection('myCollectionName');
END;
/

3.4 SODA for PL/SQLによる特定のコレクションの有無の確認

PL/SQLファンクションDBMS_SODA.open_collectionを使用すると、特定のコレクションの存在を確認できます。指定した名前のコレクションが存在しない場合は、SQLのNULL値が返されます。それ以外の場合は、コレクション・オブジェクトが返されます。

関連項目:

PL/SQLファンクションDBMS_SODA.open_collectionの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』OPEN_COLLECTIONファンクションに関する項を参照してください

例3-5 特定の名前を持つコレクションの確認

この例では、DBMS_SODA.open_collectionを使用して、myCollectionNameという名前の既存のコレクションを試しにオープンします。該当するコレクションが存在しない場合は、メッセージを出力します。

DECLARE
    collection SODA_COLLECTION_T;
BEGIN
    collection := DBMS_SODA.open_collection('myCollectionName');
    IF collection IS NULL THEN
        DBMS_OUTPUT.put_line('Collection does not exist');
    END IF;
END;
/

3.5 SODA for PL/SQLによる既存のコレクションの検出

PL/SQLファンクションDBMS_SODA.list_collection_namesを使用すると、既存のコレクションを検出できます。

関連項目:

PL/SQLファンクションDBMS_SODA.list_collection_namesの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』LIST_COLLECTION_NAMESファンクションに関する項を参照してください

例3-6 すべての既存のコレクションの名前の出力

この例では、PL/SQLファンクションDBMS_SODA.list_collection_namesを使用して、コレクション名のリストを取得します。その後で、そのリストを反復して名前を出力します。

DECLARE
    coll_list  SODA_COLLNAME_LIST_T;
BEGIN
    coll_list := DBMS_SODA.list_collection_names;
    DBMS_OUTPUT.put_line('Number of collections: ' || to_char(coll_list.count));
    DBMS_OUTPUT.put_line('Collection List: ');
    IF (coll_list.count > 0) THEN
        -- Loop over the collection name list
        FOR i IN
            coll_list.first .. coll_list.last
        LOOP
            DBMS_OUTPUT.put_line(coll_list(i));
        END LOOP;  
    ELSE   
        DBMS_OUTPUT.put_line('No collections found');
    END IF;
END;
/

3.6 SODA for PL/SQLによるドキュメント・コレクションの削除

ドキュメント・コレクションを削除するには、PL/SQLファンクションDBMS_SODA.drop_collectionを使用します。

警告:

SQLを使用して、コレクションの基礎になっているデータベースを削除しないでくださいコレクションを削除することは、そのデータベース表を削除することで終わりにはなりません。表に格納されるドキュメント以外にも、コレクションにはOracle Databaseに永続化されるメタデータも含まれています。コレクションの基礎になっている表を削除しても、コレクション・メタデータは削除されません

ノート:

SODAを使用する通常のアプリケーションを日常的に使用する場合、コレクションをドロップして再作成する必要はありません。しかし、なんらかの理由でこれを行う必要がある場合は、このガイドラインが適用されます。

多少なりともコレクションを使用しているアプリケーションがある場合は、コレクションをドロップした後に異なるメタデータで再作成しないでください。すべてのライブSODAオブジェクトが解放されるように、コレクションを再作成する前にこのようなアプリケーションをすべて停止します。

コレクションのドロップだけでは、問題は発生しません。ドロップされたコレクションの読取りまたは書込み操作でエラーが発生します。コレクションをドロップして同じメタデータを持つコレクションを再作成しても、問題はありません。ただし、異なるメタデータでコレクションを再作成して、SODAオブジェクトを使用するライブ・アプリケーションが存在する場合、古いコレクションがアクセスされるというリスクがあり、この場合、エラーは発生しません

ノート:

DBMS_SODA.drop_collectionを使用する前に、すべての書込みをコミットしてください。削除が成功するには、まず、コミットされていないコレクションへのすべての書込みをコミットするか、ロールバックする必要があります(SQL COMMITまたはROLLBACKを明示的に使用する必要があります)。そうでない場合は、例外が発生します。

関連項目:

PL/SQLファンクションDBMS_SODA.drop_collectionの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』DROP_COLLECTIONファンクションに関する項を参照してください

例3-7 ドキュメント・コレクションのドロップ

この例では、PL/SQLファンクションDBMS_SODA.drop_collectionを使用して、コレクションmyCollectionNameを削除します。

コミットされていない書込み操作があるためにコレクションを削除できない場合は、例外がスローされます。コレクションが正常に削除された場合は、ステータス1が返されます。それ以外の場合、ステータスは0になります。具体的には、指定された名前のコレクションが存在しない場合にステータス0が返されます。例外はスローされません。

DECLARE
    status  NUMBER := 0;
BEGIN
    status := DBMS_SODA.drop_collection('myCollectionName');
END;
/

3.7 SODA for PL/SQLによるドキュメントの作成

SODAドキュメントを作成するには、PL/SQLオブジェクト・タイプSODA_DOCUMENT_Tのコンストラクタを使用します。

SODA for PL/SQLでは、PL/SQLオブジェクト・タイプSODA_DOCUMENT_Tのインスタンスを使用してドキュメントを表します。このオブジェクトは、ドキュメント・コンテンツとその他のドキュメント・コンポーネントの媒体です。

次に、JSONドキュメントのコンテンツの例を示します。

{ "name" :    "Alexander",
  "address" : "1234 Main Street",
  "city" :    "Anytown",
  "state" :   "CA",
  "zip" :     "12345"
}

ドキュメントには次のコンポーネントがあります。

  • キー(Key)

  • コンテンツ(Content)

  • 作成時のタイム・スタンプ(Creation time stamp)

  • 最終変更のタイム・スタンプ(Last-modified time stamp)

  • バージョン(Version)

  • メディア・タイプ(JSONドキュメントの場合、"application/json")

ドキュメントを作成するには、SODA_DOCUMENT_Tのいずれかのコンストラクタを呼び出します。コンストラクタは、作成するドキュメントのコンテンツ・タイプ(JSONVARCHAR2CLOBまたはBLOB)に応じて異なります。データ型がJSONのドキュメントは、データベース初期化パラメータcompatible20以上である場合にのみ作成できます。

一般に、特定のコンテンツ・タイプのドキュメントは、そのタイプのドキュメント用に定義されているコンテンツ列が含まれているコレクションにのみ書込みできます。たとえば、コンテンツ・タイプがVARCHAR2のドキュメントは、VARCHAR2sqlType値を保持するcontentColumnが含まれているコレクションにのみ書込み(挿入または置換)できます。

唯一の例外は、BLOBタイプのドキュメントをJSONタイプのコンテンツ列を持つコレクションに書き込むことができることです。(データベース初期化パラメータcompatible20以上の場合は、コレクションのデフォルト・コンテンツ・タイプはJSONです。それ以外の場合はBLOBです。)

ドキュメント・コンストラクタの呼出し方法は様々ありまります。

  • ドキュメントのキーは、最初の引数として指定できます。

    コレクションでは、各ドキュメントにキーが必要です。ドキュメントを作成する場合で、ドキュメントをコレクションに挿入する必要があり、挿入されるドキュメントに対してコレクションで自動的にキーを生成しない場合にのみ、キーを指定する必要があります。デフォルトでは、コレクションは自動的にドキュメント・キーを生成するように構成されます。

  • ドキュメントのコンテンツは、必ず指定します。ドキュメントのキーも指定する場合、コンテンツはコンストラクタの2番目の引数になります。

    コンテンツのみを指定する場合は、コンテンツの仮パラメータと実パラメータの両方を関連付け矢印(=>)で区切って指定する必要があります(コンテンツ・タイプがJSONの場合はj_content => actualVARCHAR2の場合はv_content => actualCLOBの場合はc_content => actualBLOBの場合はb_content => actual)。

  • ドキュメントのメディア・タイプを指定できます。デフォルトは"application/json"です。コンテンツ・タイプがJSONでないか、すべてのパラメータ(キー、コンテンツおよびメディア・タイプ)を指定しないかぎり、メディア・タイプの仮パラメータと実パラメータの両方を関連付け矢印(=>)で区切って指定する必要があります(media_type => actual)。コンテンツ・タイプがJSONの場合、メディア・タイプは常に"application/json"です。したがって、これを指定する必要はありません。また、エラーを発生させずに"application/json"以外のものとして指定することはできません。

明示的に指定していないパラメータは、NULLにデフォルト設定されます。

ドキュメントのキーを自動的に生成するコレクションに挿入するドキュメントを作成する場合、コンテンツ・パラメータのみを指定すると便利です。クライアントでキーが割り当てられるコレクションに挿入するドキュメントを作成する場合、キーとコンテンツのみを指定すると便利です。JSON以外の("application/json"以外のメディア・タイプを使用する)ドキュメントを作成する場合、(コンテンツと)メディア・タイプを指定すると便利です。

ただし、SODA_DOCUMENT_Tコンストラクタを呼び出すことで、指定したコンポーネント(コンテンツと、キーやメディア・タイプなども)を指定した値に設定します。さらに、作成時のタイムスタンプ、最終更新時のタイムスタンプおよびバージョンの値をSQL NULL値に設定します。

オブジェクト・タイプSODA_DOCUMENT_Tには、getterメソッドがあります(これはゲッターとも呼ばれます)。それぞれのゲッターで、ドキュメントから特定のオブジェクトを取得します。(ゲッターのget_data_type()は、実際にはコンポーネント自体ではなく、コンテンツ・コンポーネントに関する情報を返します)。

表3-1 ドキュメント(SODA_DOCUMENT_T)のgetterメソッド

getterメソッド 説明

get_created_on()

ドキュメントの作成時のタイムスタンプVARCHAR2値として取得します。

get_key()

ドキュメントの一意のキーVARCHAR2値として取得します。

get_last_modified()

ドキュメントの最終変更時のタイム・スタンプVARCHAR2値として取得します。

get_media_type()

ドキュメントのメディア・タイプVARCHAR2値として取得します。

get_version()

ドキュメントのバージョンVARCHAR2値として取得します。

get_json()

ドキュメントのコンテンツJSON値として取得します。

ドキュメントのコンテンツは、JSONデータであることが必要です。それ以外の場合はエラーが発生します。

get_blob()

ドキュメントのコンテンツBLOB値として取得します。

ドキュメントのコンテンツは、BLOBデータであることが必要です。それ以外の場合はエラーが発生します。

get_clob()

ドキュメントのコンテンツCLOB値として取得します。

ドキュメントのコンテンツは、CLOBデータであることが必要です。それ以外の場合はエラーが発生します。

get_varchar2()

ドキュメントのコンテンツVARCHAR2値として取得します。

ドキュメントのコンテンツは、VARCHAR2データであることが必要です。それ以外の場合はエラーが発生します。

get_data_type()

ドキュメントのコンテンツのデータ型をPLS_INTEGER値として取得します。VARCHAR2コンテンツの場合、値はDBMS_SODA.DOC_VARCHAR2です。BLOBコンテンツの場合、値はDBMS_SODA.DOC_BLOBです。また、CLOBコンテンツの場合、値はDBMS_SODA.DOC_CLOBです。

ドキュメントの作成直後に、getterメソッドは次の値を返します。

  • コンストラクタに指定した値

  • メソッドget_media_type()の場合は"application/json" (メディア・タイプを指定しなかった場合)

  • その他のコンポーネントの場合はNULL

コンテンツ記憶域のデータ型ごとに、関連付けられたコンテンツ・コンポーネントのgetterメソッドがあります。JSONタイプの記憶域にはget_json()VARCHAR2記憶域にはget_varchar2()CLOB記憶域にはget_clob()BLOB記憶域にはget_blob()の各コンテンツ記憶域タイプに該当するgetterメソッドを使用する必要があります。そうでない場合は、エラーが発生します。

例3-8では、コンテンツのみを指定してSODA_DOCUMENT_Tインスタンスを作成します。メディア・タイプは"application/json"にデフォルト設定されます。また、その他のドキュメント・コンポーネントはNULLにデフォルト設定されます。

例3-9では、ドキュメントのキーとコンテンツを指定してSODA_DOCUMENT_Tインスタンスを作成します。メディア・タイプは"application/json"にデフォルト設定されます。また、その他のドキュメント・コンポーネントはNULLにデフォルト設定されます。

関連項目:

  • SODAドキュメントの概要については、『Oracle Database Simple Oracle Document Access (SODA)の概要』SODAドキュメントの概要に関する項を参照してください

  • SODAドキュメントに適用される制限事項については、『Oracle Database Simple Oracle Document Access (SODA)の概要』SODAの制限事項(リファレンス)に関する項を参照してください

  • オブジェクト・タイプSODA_DOCUMENT_Tのコンストラクタとgetterメソッドの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』SODA_COLLECTION_Tタイプに関する項を参照してください

例3-8 JSONコンテンツを含むドキュメントの作成

この例では、コンテンツ・タイプごとのSODA_DOCUMENT_Tのコンストラクタを使用して3つのドキュメントを作成します。この例では、ドキュメント・コンテンツのみを指定しています(それぞれに同じコンテンツを使用します)。

コンテンツ・パラメータは、それぞれの場合で異なります(コンテンツの格納に使用するSQLデータ型を指定します)。ここでは、最初のドキュメントの作成ではコンテンツ・パラメータj_contentを使用して、JSONタイプのコンテンツを指定しています。2番目ではv_contentを使用して、VARCHAR2コンテンツを指定しています。3番目ではパラメータc_contentを使用して、CLOBコンテンツを指定しています。4番目ではパラメータb_contentを使用して、BLOBコンテンツを指定しています。

データ型JSONのドキュメントでは、リテラルのVARCHAR2文字列入力がJSONコンストラクタにラップされることに注意してください。また、Oracle SQLファンクションjson_serializeを使用してテキストにシリアライズされたドキュメント・コンテンツを出力します。

各ドキュメントの作成後に、この例では、getterメソッドを使用してドキュメントのコンテンツを取得します。それぞれのコンテンツ記憶域タイプに応じたgetterメソッドが使用されている点に注目してください(JSONコンテンツにはget_json()など)。

データベース初期化パラメータcompatible20以上である場合、例3-3で作成したコレクションへの書込みには、そのコレクションにデフォルト・メタデータが含まれているため、コンテンツ・タイプがJSONのドキュメントが適切です。compatibleが20未満の場合、コンテンツ・タイプBLOBのドキュメントがそのコレクションへの書込みに適しています。

デフォルトのメタデータは、最初のケースではJSONドキュメント・コンテンツ(JSONタイプのコンテンツのみが受け入れられる)を示し、2番目のケースではBLOBコンテンツ(BLOBタイプのコンテンツのみが受け入れられる)を示します。コレクションに誤ったコンテンツ・タイプのJSONデータを挿入しようとすると、エラーが発生します。

ただし、例外として、BLOB JSONドキュメントをJSONタイプ・コレクションに挿入できます。この例外を除いて、同じSQLタイプのドキュメントのみをコレクションに挿入できます。たとえば、VARCHAR2 JSONドキュメントが挿入できるのは、コンテンツ列のタイプがVARCHAR2コレクションのみです。

DECLARE
    j_doc  SODA_DOCUMENT_T;
    v_doc  SODA_DOCUMENT_T;
    b_doc  SODA_DOCUMENT_T;
    c_doc  SODA_DOCUMENT_T;
BEGIN
    -- Create JSON type document
    j_doc := SODA_DOCUMENT_T(j_content => JSON('{"name" : "Alexander"}'));
    DBMS_OUTPUT.put_line('JSON type doc content: ' || JSON_SERIALIZE(j_doc.get_json));
    
    -- Create VARCHAR2 document
    v_doc := SODA_DOCUMENT_T(v_content => '{"name" : "Alexander"}');
    DBMS_OUTPUT.put_line('VARCHAR2 doc content: ' || v_doc.get_varchar2);
    
    -- Create BLOB document
    b_doc := SODA_DOCUMENT_T(
               b_content => utl_raw.cast_to_raw('{"name" : "Alexander"}'));
    DBMS_OUTPUT.put_line('BLOB doc content: ' ||
                         utl_raw.cast_to_varchar2(b_doc.get_blob));

    -- Create CLOB document
    c_doc := SODA_DOCUMENT_T(c_content => '{"name" : "Alexander"}');
    DBMS_OUTPUT.put_line('CLOB doc content: ' || c_doc.get_clob);
END;
/

例3-9 ドキュメント・キーおよびJSONコンテンツを含むドキュメントの作成

この例は、例3-8と似ていますが、ドキュメント・コンテンツとともにドキュメント・キー(myKey)も指定しています。

DECLARE
    j_doc  SODA_DOCUMENT_T;
    v_doc  SODA_DOCUMENT_T;
    b_doc  SODA_DOCUMENT_T;
    c_doc  SODA_DOCUMENT_T;
BEGIN

    -- Create JSON type document
    j_doc := SODA_DOCUMENT_T('myKey' , j_content => JSON('{"name" : "Alexander"}'));
    DBMS_OUTPUT.put_line('JSON type doc key: ' || j_doc.get_key);
    DBMS_OUTPUT.put_line('JSON doc content: ' || JSON_SERIALIZE(j_doc.get_json));
        
    -- Create VARCHAR2 document
    v_doc := SODA_DOCUMENT_T('myKey' , v_content => '{"name" : "Alexander"}');
    DBMS_OUTPUT.put_line('VARCHAR2 doc key: ' || v_doc.get_key);
    DBMS_OUTPUT.put_line('VARCHAR2 doc content: ' || v_doc.get_varchar2);
        
    -- Create BLOB document
    b_doc := SODA_DOCUMENT_T('myKey' ,
                             b_content => utl_raw.cast_to_raw('{"name" : "Alexander"}'));
    DBMS_OUTPUT.put_line('BLOB doc key: ' || b_doc.get_key);
    DBMS_OUTPUT.put_line('BLOB doc content: ' ||
                         utl_raw.cast_to_varchar2(b_doc.get_blob));
    
    -- Create CLOB document
    c_doc := SODA_DOCUMENT_T('myKey' , c_content => '{"name" : "Alexander"}');
    DBMS_OUTPUT.put_line('CLOB doc key: ' || c_doc.get_key);
    DBMS_OUTPUT.put_line('CLOB doc content: ' || c_doc.get_clob);
END;
/

3.8 SODA for PL/SQLによるコレクションへのドキュメントの挿入

コレクションにドキュメントを挿入するには、SODA_COLLECTION_Tのメソッド(メンバー・ファンクション) insert_one()またはinsert_one_and_get()を呼び出します。コレクションがクライアント割当てキーで構成されておらず、入力ドキュメントがキーを指定していない場合、これらのメソッドでは、ドキュメント・キーが自動的に作成されます。

メソッドinsert_one()とメソッドinsert_one_and_get()は、どちらもコレクションにドキュメントを挿入して、作成時のタイムスタンプ、最終変更時のタイムスタンプおよびバージョンの値を自動的に設定します(これらのコンポーネントが含まれるようにしてバージョンが自動的に生成されるようにコレクションを構成した場合。これはデフォルトの構成です)。

ドキュメントを挿入すると、現在の値がNULLのドキュメント・コンポーネント(それらのコンポーネントの値を指定しないでドキュメントを作成した結果の値)は、自動生成される適切な値に更新されます。その後、ドキュメントに対するその他のSODA操作では、最終更新時のタイムスタンプとバージョンのコンポーネントが自動的に更新されます。

ドキュメントの挿入に加えて、insert_one_and_getは結果のドキュメントも返します。これには、生成されたドキュメント・コンポーネント(キーなど)が含まれていますが、挿入したドキュメントのコンテンツは含まれていません。

ノート:

コレクションがクライアント割当てドキュメント・キーで構成されていて(デフォルトの場合と異なるケース)、入力ドキュメントがコレクション内の既存のドキュメントを識別するキーを提供している場合、これらのメソッドは例外をスローします。

メソッドinsert_one_and_get()は、オプションの2番目の引数hintを受け入れます。この引数の値はSODAの基礎になっているSQLコードのヒントとして渡されます。引数のVARCHAR2値は、SQLヒント構文(つまり、/*+...*/で囲むSQLコメント構文がないヒント・テキスト)を使用します。ヒントMONITOR(モニタリングをオン)またはNO_MONITOR(モニタリングをオフ)のみを使用します。

(これを使用してSQLヒントを渡すことができますが、MONITORNO_MONITORはSODAに有用なヒントであり、適切でないヒントによってオプティマイザが最適でない問合せ計画を生成する可能性があります。)

関連項目:

  • SODA_COLLECTION_Tのメソッドinsert_one()の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』INSERT_ONEファンクションに関する項を参照してください

  • SODA_COLLECTION_Tのメソッドinsert_one_and_get()の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』SODA_COLLECTION_Tタイプに関する項を参照してください

  • SODA_DOCUMENT_Tのgetterメソッドの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』SODA_DOCUMENT_Tタイプに関する項を参照してください

  • データベース操作のモニタリングの詳細は、『Oracle Database SQLチューニング・ガイド』データベース操作のモニタリングに関する項を参照してください

  • SQLヒントMONITORおよびNO_MONITORの構文と動作の詳細は、『Oracle Database SQLチューニング・ガイド』MONITORおよびNO_MONITORのヒントに関する項を参照してください

例3-10 コレクションへのドキュメントの挿入

この例では、ドキュメントを作成して、SODA_COLLECTION_Tのメソッドinsert_one()を使用してコレクションに挿入します。

DECLARE
    collection  SODA_COLLECTION_T;
    document    SODA_DOCUMENT_T;
    status      NUMBER;
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');
    document :=
      SODA_DOCUMENT_T(
        b_content => utl_raw.cast_to_raw('{"name" : "Alexander"}'));

    -- Insert a document
    status := collection.insert_one(document);
END;
/

例3-11 コレクションへのドキュメントの挿入および結果ドキュメントの取得

この例では、ドキュメントを作成して、メソッドinsert_one_and_get()を使用してコレクションに挿入します。その後で、結果のドキュメントから生成されたコンポーネント(結果に含まれる)を取得(および出力)します。コンポーネントを取得するために、SODA_DOCUMENT_Tのメソッドget_key()get_created_on()get_last_modified()およびget_version()を使用します。

DECLARE
    collection  SODA_COLLECTION_T;
    document    SODA_DOCUMENT_T;
    ins_doc     SODA_DOCUMENT_T;
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');
    document :=
      SODA_DOCUMENT_T(
        b_content => utl_raw.cast_to_raw('{"name" : "Alexander"}'));
    ins_doc := collection.insert_one_and_get(document);

    -- Insert the document and get its components
    IF ins_doc IS NOT NULL THEN
        DBMS_OUTPUT.put_line('Inserted document components:');
        DBMS_OUTPUT.put_line('Key: ' || ins_doc.get_key);
        DBMS_OUTPUT.put_line('Creation timestamp: '
                             || ins_doc.get_created_on);
        DBMS_OUTPUT.put_line('Last modified timestamp: '
                             || ins_doc.get_last_modified);
        DBMS_OUTPUT.put_line('Version: ' || ins_doc.get_version);
    END IF;
END;
/

3.9 SODA for PL/SQLによるコレクションへのドキュメントの保存

SODA_DOCUMENT_Tのメソッドsave()またはsave_and_get()を使用して、ドキュメントをコレクションに保存できます。つまり、ドキュメントが新規の場合は挿入し、すでにコレクションに属している場合は更新します。(このような操作は「アップサート」と呼ばれることがあります。)

メソッドsave_and_get()insert()と同等で、save_and_get()insert_one_and_get()と同等ですが、次の違いがあります: クライアント割当てキーが使用され、指定したキーを持つドキュメントがコレクションにすでに属している場合、そのドキュメントは入力ドキュメントで置換されます。

コレクションがクライアント割当てキーで構成されておらず、キーが入力ドキュメントに指定されていない場合、挿入時に、これらのメソッドによってキーが自動的に作成されます。

メソッドsave_and_get()は、オプションの2番目の引数hintを受け入れます。この引数の値はSODAの基礎になっているSQLコードのヒントとして渡されます。引数のVARCHAR2値は、SQLヒント構文(つまり、/*+...*/で囲むSQLコメント構文がないヒント・テキスト)を使用します。ヒントMONITOR(モニタリングをオン)またはNO_MONITOR(モニタリングをオフ)のみを使用します。

(これを使用してSQLヒントを渡すことができますが、MONITORNO_MONITORはSODAに有用なヒントであり、適切でないヒントによってオプティマイザが最適でない問合せ計画を生成する可能性があります。)

関連項目:

  • データベース操作のモニタリングの詳細は、『Oracle Database SQLチューニング・ガイド』データベース操作のモニタリングに関する項を参照してください

  • SQLヒントMONITORおよびNO_MONITORの構文と動作の詳細は、『Oracle Database SQLチューニング・ガイド』MONITORおよびNO_MONITORのヒントに関する項を参照してください

例3-12 SODA for PL/SQLによるコレクションへのドキュメントの保存

この例では、コレクションと2つのドキュメントを作成し、save()メソッドを使用してドキュメントをコレクションに保存し、挿入します。次の例では、ドキュメントのコンテンツを変更し、再度保存します。これにより、既存のドキュメントが置換されます。

DECLARE
    coll  SODA_COLLECTION_T;
    md    VARCHAR2(4000);
    doca  SODA_DOCUMENT_T;
    docb  SODA_DOCUMENT_T;
    n     NUMBER;
BEGIN
    -- Create a collection and print its metadata
    md := '{"keyColumn":{"assignmentMethod":"CLIENT"}}';
    coll := DBMS_SODA.create_collection('SODAPLS_SAVE01', md);
    DBMS_OUTPUT.put_line('Coll: ' ||
                         json_query(coll.get_metadata, '$' pretty));
    
    -- Create two documents.
    doca := SODA_DOCUMENT_T('a', b_content =>
                                   utl_raw.cast_to_raw('{"a" : "value A" }'));
    docb := SODA_DOCUMENT_T('b', b_content =>
                                   utl_raw.cast_to_raw('{"b" : "value B" }'));

    -- Save the documents.  They are new, so this inserts them.
    n := coll.save(doca);
    DBMS_OUTPUT.put_line('Status: ' || n);
    n := coll.save(docb);
    DBMS_OUTPUT.put_line('Status: ' || n);

    -- Rewrite the content of the documents
    doca := SODA_DOCUMENT_T('a', b_content =>
                                   utl_raw.cast_to_raw('{"a" : "new value A" }'));
    docb := SODA_DOCUMENT_T('b', b_content =>
                                   utl_raw.cast_to_raw('{"b" : "new value B" }'));

    -- Save the existing documents, replacing them.
    n := coll.save(doca);
    DBMS_OUTPUT.put_line('Status: ' || n);
    n := coll.save(docb);
    DBMS_OUTPUT.put_line('Status: ' || n);
END;
/

3.10 SODA for PLSQLの読取りおよび書込み操作

SODA_OPERATION_Tインスタンスは、SODA_COLLECTION_Tのメソッドfind()によって返されます。SODA_OPERATION_Tのメソッドをつなげて、コレクションに対して読取りおよび書込み操作を指定できます。

ノート:

データ型SODA_OPERATION_Tは、Oracle Database 18.3でSODA for PL/SQLに追加されました。これを使用するにはそのデータベース・リリース以降が必要となります。

通常、SODA_OPERATION_Tを使用して、すべてのSODA読取り操作、およびドキュメントの挿入やコレクションへの保存以外の書込み操作をすべて指定します。SODA_OPERATION_Tの非ターミナル・メソッドをつないで、スコープまたは条件を絞り込んだり、読取りまたは書込み操作を限定したりします。

非ターミナル・メソッドは、それらが呼び出されたインスタンスと同じSODA_OPERATION_Tインスタンスを返すため、それらをつなぐことができます。非ターミナル・メソッドは次のとおりです。

  • acquire_lock() — ドキュメントをロックします(ペシミスティック・ロック)。

  • as_of_scn() - 特定のシステム変更番号(SCN)時点のドキュメントにアクセスします。ここでは、Oracle Flashback Query SELECT AS OFを使用します。

  • as_of_timestamp() - 指定した日時時点のドキュメントにアクセスします。ここでは、Oracle Flashback Query SELECT AS OFを使用します。

  • filter() - 例による問合せを使用してドキュメントをフィルタします(QBEは、フィルタ指定とも呼ばれます)。

  • hint() - ヒントを指定して、問合せのリアルタイムSQLモニタリングのオンとオフを切り替えます。

    引数のVARCHAR2値は、SQLヒント構文(つまり、/*+...*/で囲むSQLコメント構文がないヒント・テキスト)を使用します。ヒントMONITOR(モニタリングをオン)またはNO_MONITOR(モニタリングをオフ)のみを使用します。ヒントは、SODAの基礎となるSQLコードに渡されます。

    (これを使用してSQLヒントを渡すことができますが、MONITORNO_MONITORはSODAに有用なヒントであり、適切でないヒントによってオプティマイザが最適でない問合せ計画を生成する可能性があります。)

  • key() - 特定のドキュメントを一意のキーで指定します。

  • keys() - 特定のドキュメントを一意のキーで指定します。

    引数として渡される最大キー数は1000を超えることはできません。超えると、ランタイム・エラーが発生します。

  • limit() - 読取り操作で返すことができるドキュメントの数を制限します。

  • skip() - 他のドキュメントを返す前に、読取り時にスキップするドキュメントの数を指定します。

  • version() - 指定したドキュメントの特定のバージョンを指定します。

チェーンの最後のSODA_OPERATION_Tターミナル・メソッドでは、実際の読取りまたは書込み操作が実行されます。読取り操作のターミナル・メソッドは次のとおりです。

  • count() - 読取り操作によって検出されたドキュメントをカウントします。

  • get_cursor() - 複数のドキュメントを取得します。(読取り操作の結果によってカーソルを取得します。)

  • get_data_guide() - 読取り操作によって検出されたドキュメントのデータ・ガイドを取得します。

  • get_one() - 単一のドキュメントを取得します。

書込み操作のターミナル・メソッドは次のとおりです。

  • remove() - コレクションからドキュメントを削除します。

  • replace_one() - コレクション内の1つのドキュメントを置換します。

  • replace_one_and_get() - 1つのドキュメントを置換して、新しい(結果)ドキュメントを返します。

ドキュメントに記述がなければ、すべての非ターミナル・メソッドをつなぎ、ターミナル・メソッドでチェーンを終了できます。ただし、すべての組合せに意味があるわけではありません。たとえば、keys()などのドキュメントを一意に識別しないメソッドとversion()メソッドをつなげても意味がありません。

関連項目:

  • Oracle Flashback Queryの詳細は、『Oracle Database SQL言語リファレンス』Oracle Flashback Query (SELECT AS OF)の使用に関する項を参照してください

  • 各メソッドを含むSODA_OPERATION_Tの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』SODA_OPERATION_Tタイプに関する項を参照してください

  • データベース操作のモニタリングの詳細は、『Oracle Database SQLチューニング・ガイド』データベース操作のモニタリングに関する項を参照してください

  • SQLヒントMONITORおよびNO_MONITORの構文と動作の詳細は、『Oracle Database SQLチューニング・ガイド』MONITORおよびNO_MONITORのヒントに関する項を参照してください

  • SODAの制限事項の詳細は、『Oracle Database Simple Oracle Document Access (SODA)の概要』SODAの制限事項(リファレンス)に関する項を参照してください

3.11 SODA for PL/SQLによるコレクション内のドキュメントの検索

SODA_OPERATION_Tのターミナル・メソッドget_one()またはget_cursor()を使用すると、コレクション内の1つまたは複数のドキュメントをそれぞれ検索できます。ターミナル・メソッドcount()を使用すると、コレクション内のドキュメントをカウントできます。key()keys()filter()などの非ターミナル・メソッドを使用すると、検索操作の条件を指定できます。

非ターミナルSODA_OPERATION_Tのメソッドhint()を使用して、SQLモニタリングをオンまたはオフにするSQLヒントを提供できます。非ターミナル・メソッドas_of_scn()およびas_of_timestamp()を使用して、特定のシステム変更番号(SCN)または特定の日時時点のドキュメントにアクセスできます。

ノート:

データ型SODA_OPERATION_Tは、Oracle Database 18.3でSODA for PL/SQLに追加されました。これを使用するにはそのデータベース・リリース以降が必要となります。

関連項目:

  • SODA_COLLECTION_Tのメソッドfind()の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』FINDファンクションに関する項を参照してください

  • データ型SODA_OPERATION_Tとそのメソッドの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』SODA_OPERATION_Tタイプに関する項を参照してください

  • SODA_DOCUMENT_Tのgetterメソッドの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』SODA_DOCUMENT_Tタイプに関する項を参照してください

  • SQL/JSONファンクションjson_queryの詳細は、『Oracle Database SQL言語リファレンス』JSON_QUERYに関する項を参照してください

  • データベース操作のモニタリングの詳細は、『Oracle Database SQLチューニング・ガイド』データベース操作のモニタリングに関する項を参照してください

  • SQLヒントMONITORおよびNO_MONITORの構文と動作の詳細は、『Oracle Database SQLチューニング・ガイド』MONITORおよびNO_MONITORのヒントに関する項を参照してください

例3-13 SODA for PL/SQLによるコレクション内のすべてのドキュメントの検索

この例では、SODA_COLLECTION_Tのメソッドfind()およびSODA_OPERATION_TのメソッドgetCursor()を使用して、コレクション内の各ドキュメントを含む問合せ結果リストのカーソルを取得します。次にWHILE文のカーソルを使用し、結果リスト内の各ドキュメントのコンテンツを文字列として取得して出力します。最後にカーソルをクローズします。

出力するドキュメント・コンポーネントを取得するために、SODA_DOCUMENT_Tのメソッドget_key()get_blob()get_created_on()get_last_modified()およびget_version()が使用されています。ドキュメントのコンテンツをSQL/JSONファンクションのjson_queryに渡し、整形出力します(キーワードPRETTYを使用)。

ノート:

リソース・リークを回避するには、不要なカーソルをすべてクローズします

DECLARE
    collection    SODA_COLLECTION_T;
    document      SODA_DOCUMENT_T;
    cur           SODA_CURSOR_T;
    status        BOOLEAN;
BEGIN
    -- Open the collection to be queried
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Open the cursor to fetch the documents.
    cur := collection.find().get_cursor();

    -- Loop through the cursor
    WHILE cur.has_next
    LOOP
      document := cur.next;
      IF document IS NOT NULL THEN
          DBMS_OUTPUT.put_line('Document components:');
          DBMS_OUTPUT.put_line('Key: ' || document.get_key);
          DBMS_OUTPUT.put_line('Content: '
            || json_query(document.get_blob, '$' PRETTY));
          DBMS_OUTPUT.put_line('Creation timestamp: '
            || document.get_created_on);
          DBMS_OUTPUT.put_line('Last modified timestamp: '
            || document.get_last_modified);
          DBMS_OUTPUT.put_line('Version: ' || document.get_version);
      END IF;
    END LOOP;

    -- IMPORTANT: You must close the cursor, to release resources.
    status := cur.close;
END;
/

例3-14 SODA for PL/SQLによる特定のドキュメント・キーを持つ一意のドキュメントの検索

この例では、SODA_COLLECTION_Tのメソッドfind()key()およびget_one()を使用して、キーが"key1"の一意のドキュメントを検索します。

DECLARE
    collection  SODA_COLLECTION_T;
    document    SODA_DOCUMENT_T;
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Find a document using a key
    document := collection.find().key('key1').get_one;

    IF document IS NOT NULL THEN
        DBMS_OUTPUT.put_line('Document components:');
        DBMS_OUTPUT.put_line('Key: ' || document.get_key);
        DBMS_OUTPUT.put_line('Content: '
          || JSON_QUERY(document.get_blob, '$' PRETTY));
        DBMS_OUTPUT.put_line('Creation timestamp: '
          || document.get_created_on);
        DBMS_OUTPUT.put_line('Last modified timestamp: '
          || document.get_last_modified);
        DBMS_OUTPUT.put_line('Version: ' || document.get_version);
    END IF;
END;
/

例3-15 SODA for PL/SQLによるドキュメント・キーを指定した複数のドキュメントの検索

この例では、(文字列の)キー"key1""key2"および"key3"を指定してキーリストmyKeysを定義します。その後、それらのキーを持つドキュメントが検索され、それらのコンポーネントが出力されます。SODA_COLLECTION_Tのメソッドkeys()では、特定のキーのドキュメントを指定します。

DECLARE
    collection  SODA_COLLECTION_T;
    document    SODA_DOCUMENT_T;
    cur         SODA_CURSOR_T;
    status      BOOLEAN;
    myKeys      SODA_KEY_LIST_T;
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Set the keys list
    myKeys := SODA_KEY_LIST_T('key1', 'key2', 'key3');

    -- Find documents using keys
    cur := collection.find().keys(myKeys).get_cursor;

    -- Loop through the cursor
    WHILE cur.has_next
    LOOP
      document := cur.next;
      IF document IS NOT NULL THEN
          DBMS_OUTPUT.put_line('Document components:');
          DBMS_OUTPUT.put_line('Key: ' || document.get_key);
          DBMS_OUTPUT.put_line('Content: '
            || json_query(document.get_blob, '$' PRETTY));
          DBMS_OUTPUT.put_line('Creation timestamp: '
            || document.get_created_on);
          DBMS_OUTPUT.put_line('Last modified timestamp: '
            || document.get_last_modified);
          DBMS_OUTPUT.put_line('Version: ' || document.get_version);
      END IF;
    END LOOP;
    status := cur.close;
END;
/

例3-16 SODA for PL/SQLによるフィルタ指定を使用したドキュメントの検索

SODA_OPERATION_Tのメソッドfilter()では、コレクション内のJSONドキュメントをフィルタする強力な方法を提供します。そのパラメータはJSONの例による問合せ(QBE、フィルタ仕様とも呼ばれる)です。

フィルタ指定の構文には、表現力のあるJSONドキュメントのパターン・マッチング言語を使用します。この例では、SODA for PL/SQLでQBEを使用する方法を示すためだけの非常に簡単なQBEのみを使用しています。

この例では、次の操作を行います。

  1. nameフィールドの値が"Alexander"のすべてのJSONドキュメントを検索するフィルタ仕様を作成します。

  2. フィルタ仕様を使用して一致するドキュメントを検索します。

  3. 各ドキュメントのコンポーネントを出力します。

DECLARE
    collection  SODA_COLLECTION_T;
    document    SODA_DOCUMENT_T;
    cur         SODA_CURSOR_T;
    status      BOOLEAN;
    qbe         VARCHAR2(128);
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Define the filter specification (QBE)
    qbe := '{"name" : "alexander"}';

    -- Open a cursor for the filtered documents
    cur := collection.find().filter(qbe).get_cursor;

    -- Loop through the cursor
    WHILE cur.has_next
    LOOP
      document := cur.next;
      IF document IS NOT NULL THEN
          DBMS_OUTPUT.put_line('Document components:');
          DBMS_OUTPUT.put_line('Key: ' || document.get_key);
          DBMS_OUTPUT.put_line('Content: '
            || JSON_QUERY(document.get_blob, '$' PRETTY));
          DBMS_OUTPUT.put_line('Creation timestamp: '
            || document.get_created_on);
          DBMS_OUTPUT.put_line('Last modified timestamp: '
            || document.get_last_modified);
          DBMS_OUTPUT.put_line('Version: ' || document.get_version);
      END IF;
    END LOOP;
    status := cur.close;
END;
/

関連項目:

例3-17 SODA for PL/SQLによるメソッドskip()およびlimit()を使用したページ区切り問合せの指定

この例では、ページ区切り問合せでSODA_OPERATION_Tのメソッドfilter()skip()およびlimit()を使用します。

DECLARE
    collection  SODA_COLLECTION_T;
    document    SODA_DOCUMENT_T;
    cur         SODA_Cursor_T;
    status      BOOLEAN;
    qbe         VARCHAR2(128);
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Define the filter
    qbe := '{"name" : "Alexander"}';

    -- Find all documents that match the QBE, skip over the first 1000
    -- of them, limit the number of returned documents to 100
    cur := collection.find().filter(qbe).skip(1000).limit(100).get_cursor;

    -- Loop through the cursor
    WHILE cur.has_next
    LOOP
      document := cur.next;
      IF document IS NOT NULL THEN
          DBMS_OUTPUT.put_line('Document components:');
          DBMS_OUTPUT.put_line('Key: ' || document.get_key);
          DBMS_OUTPUT.put_line('Content: ' ||
                               JSON_QUERY(document.get_blob, '$' PRETTY));
          DBMS_OUTPUT.put_line('Creation timestamp: ' || 
                               document.get_created_on);
          DBMS_OUTPUT.put_line('Last modified timestamp: ' ||
                               document.get_last_modified);
          DBMS_OUTPUT.put_line('Version: ' || document.get_version);
      END IF;
    END LOOP;
    status := cur.close;
END;
/

例3-18 SODA for PL/SQLによるドキュメント・バージョンの指定

この例では、SODA_OPERATION_Tのメソッドversion()を使用して、ドキュメント・バージョンを指定します。これは、書込み操作用のターミナル・メソッドとともに使用する場合、オプティミスティック・ロックの実装に便利です。

通常、version()は、ドキュメントを指定するkey()メソッドと一緒に使用します。keyLike()メソッドおよびfilter()メソッドとともにversion()を使用することもできます(1つのドキュメントのみが識別される場合)。

DECLARE
    collection  SODA_COLLECTION_T;
    document    SODA_DOCUMENT_T;
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Find a particular version of the document that has a given key
    document := collection.find().key('key1').version('version1').get_one;

    IF document IS NOT NULL THEN
        DBMS_OUTPUT.put_line('Document components:');
        DBMS_OUTPUT.put_line('Key: ' || document.get_key);
        DBMS_OUTPUT.put_line('Content: ' ||
          JSON_QUERY(document.get_blob, '$' PRETTY));
        DBMS_OUTPUT.put_line('Creation timestamp: '
          || document.get_created_on);
        DBMS_OUTPUT.put_line('Last modified timestamp: '
          || document.get_last_modified);
        DBMS_OUTPUT.put_line('Version: ' || document.get_version);
    END IF;
END;
/

例3-19 見つかったドキュメントの数のカウント

この例では、SODA_OPERATION_Tのメソッドcount()を使用して、コレクション内のすべてのドキュメントの件数を取得します。その後、フィルタ指定(QBE)によって返されたすべてのドキュメントの件数が取得されます。

DECLARE
    collection  SODA_COLLECTION_T;
    num_docs    NUMBER;
    qbe         VARCHAR2(128);
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Count of all documents in the collection
    num_docs := collection.find().count;
    DBMS_OUTPUT.put_line('Count (all): ' || num_docs);
    
    -- Set the filter
    qbe := '{"name" : "Alexander"}';

    -- Count of all documents in the collection that match
    -- a filter spec
    num_docs := collection.find().filter(qbe).count;
    DBMS_OUTPUT.put_line('Count (filtered): ' || num_docs);
/

例3-20 SODA for PL/SQLによる過去(フラッシュバック)のコレクションのドキュメントの取得

このコードでは、SODA_OPERATION_Tのメソッドas_of_timestamp()を使用して、2021年4月27日のUTC時間5:00 (ISO 8601の日時文字列2021-04-27T05:00:00Zで表される時間)に、コレクションmyCollectionNameにあったドキュメントに対してカーソルを開きます。

DECLARE
  coll    SODA_COLLECTION_T;
  cur     SODA_CURSOR_T;
  b       BOOLEAN;
BEGIN
  -- Open the collection to be queried
  coll := DBMS_SODA.open_collection('myCollectionName');

  -- Specify SCN to retrieve documents as it existed then
  cur := coll.find().as_of_timestamp('2021-04-27T05:00:00Z').get_cursor;
  b := cur.close;
END;
/

同様に、このコードでは、SODA_OPERATION_Tのメソッドas_of_scn()を使用して、論理的な内部タイムスタンプであるOracle Databaseのシステム変更番号(SCN)を使用して、特定の時点に存在するドキュメントにアクセスします。

DECLARE
  coll    SODA_COLLECTION_T;
  cur     SODA_CURSOR_T;
  b       BOOLEAN;
BEGIN
  -- Open the collection to be queried
  coll := DBMS_SODA.open_collection('myCollectionName');

  -- Specify SCN to retrieve documents as it existed then
  cur := coll.find().as_of_scn(2068287).get_cursor;
  b := cur.close;
END;
/

例3-21 SODA for PL/SQLによる異機種間コレクション内のドキュメントの検索時の全文検索の使用

この例では、QBE演算子$textContainsを使用して、メディア・タイプ列を持つ異機種コレクションの全文検索を実行します。たとえば、Microsoft Word、Portable Document Format (PDF)およびプレーンテキスト・ドキュメントはすべて、$textContainsを使用して検索できます。

(JSONドキュメントのコレクションの全文検索を実行するには、$textContainsではなくQBE演算子$containsを使用します。)

この例の検索パターンはRogersです。これは、コレクションmyTextCollectionのドキュメント内の任意の場所のリテラル・テキストを検索することを意味します。

DECLARE
  coll    SODA_COLLECTION_T;
  cur     SODA_CURSOR_T;
  qbe     VARCHAR2(100);
  b       BOOLEAN;
BEGIN
  -- Open the collection to be queried
  coll := DBMS_SODA.open_collection('myTextCollection');

  -- Use $textContains operator to specify the subtring
  qbe := '{"$textContains" : "Rogers"}';
  cur := coll.find().filter(qbe).get_cursor;
  b := cur.close;
END;
/

$textContainsの検索パターン値の構文はSQLファンクションcontainsと同じであり、その結果の動作も同じです。たとえば、これは、他のテキスト付近にあるテキストを問い合せたり、問合せであいまいパターン一致を使用できるということです。(検索パターン引数に、Oracle Textの検索で予約されている文字または単語が含まれる場合は、その文字または単語をエスケープする必要があります。)

演算子$textContainsを使用してコレクションを検索するには、SQLを使用してコレクションのコンテンツ列にOracle Text検索索引を定義しておく必要があります。このSQLコードによって、コレクションmyTextCollectionのコンテンツ列myContentColumnに索引mySearchIndexが作成されます。

CREATE SEARCH INDEX mySearchIndex ON
  myTextCollection(myContentColumn)

関連項目:

3.12 SODA for PL/SQLによるコレクション内のドキュメントの置換

SODA_OPERATION_Tの置換操作メソッドreplace_one()またはreplace_one_and_get()を非ターミナル・メソッドkey()とつなぐと、置換されるドキュメントを一意に識別できます。必要に応じて、version()filter()などの追加の非ターミナル・メソッドを使用できます。非ターミナル・メソッドacquire_lock()を使用して、更新のためにドキュメントをロックできます。

ノート:

データ型SODA_OPERATION_Tは、Oracle Database 18.3でSODA for PL/SQLに追加されました。これを使用するにはそのデータベース・リリース以降が必要となります。

replace_one()メソッドおよびreplace_one_and_get()メソッドは、コンテンツを置き換えるだけでなく、最終変更のタイムスタンプとバージョンの値を更新します。置き換えてもドキュメント・キーまたは作成時のタイムスタンプは変更されません

関連項目:

  • SODA_COLLECTION_Tのメソッドfind()の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』FINDファンクションに関する項を参照してください

  • データ型SODA_OPERATION_Tとそのメソッドの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』SODA_OPERATION_Tタイプに関する項を参照してください

  • SODA_OPERATION_Tのメソッドreplace_one()の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』REPLACE_ONEファンクションに関する項を参照してください

  • SODA_OPERATION_Tのメソッドreplace_one_and_get()の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』REPLACE_ONE_AND_GETファンクションに関する項を参照してください

  • SODA_OPERATION_Tのメソッドacquire_lock()の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』ACQUIRE_LOCKファンクションに関する項を参照してください

  • SODA_DOCUMENT_Tのgetterメソッドの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』SODA_DOCUMENT_Tタイプに関する項を参照してください

例3-22 SODA for PL/SQLによる特定のキーを持つドキュメントの置換および結果のドキュメントの取得

この例では、コレクション内の特定のキーを持つドキュメントを置換します。その後で、結果のドキュメントからキーと生成されたコンポーネントを取得(および出力)します。コンポーネントを取得するために、SODA_DOCUMENT_Tのメソッドget_key()get_created_on()get_last_modified()およびget_version()を使用します。

DECLARE
    collection  SODA_COLLECTION_T;
    document    SODA_DOCUMENT_T;
    new_doc     SODA_DOCUMENT_T;
BEGIN
    collection := DBMS_SODA.open_collection('myCollectionName');
    document := SODA_DOCUMENT_T(
                  b_content => utl_raw.cast_to_raw('{"name" : "Sriky"}'));
    new_doc := collection.find().key('key1').replace_one_and_get(document);

    IF new_doc IS NOT NULL THEN
        DBMS_OUTPUT.put_line('Document components:');
        DBMS_OUTPUT.put_line('Key: ' || new_doc.get_key);
        DBMS_OUTPUT.put_line('Creation timestamp: ' || new_doc.get_created_on);
        DBMS_OUTPUT.put_line('Last modified timestamp: ' ||
                             new_doc.get_last_modified);
        DBMS_OUTPUT.put_line('Version: ' || new_doc.get_version);
    END IF;
END;
/

例3-23 SODA for PL/SQLによる特定のバージョンのドキュメントの置換

ドキュメントを置換する場合にオプティミスティック・ロックを実装するには、この例のようにメソッドkey()およびversion()をつなげることができます。書込み操作(replace_one_and_get)は、既知の最新バージョン(ここではversion1)の変更を最適化して試行します。

NULLを最後に読み取ってから他のトランザクションがドキュメントを変更したために書込みに失敗した場合(NULLを返す)、書込みが成功するまで再試行を繰り返す必要があります。ドキュメントを再度読み取り、新しいバージョンを取得して、新しい書込みの試行でそのバージョンを指定します。この例では、単一の書込み試行のみを示します。

DECLARE
    collection  SODA_COLLECTION_T;
    document    SODA_DOCUMENT_T;
    new_doc     SODA_DOCUMENT_T;
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Replace content of version 'version1' of the document that has key 'key1'
    new_doc := SODA_DOCUMENT_T(
                  b_content => utl_raw.cast_to_raw('{"name" : "Sriky"}'));
    document := collection.find().key('key1').version('version1').replace_one_and_get(new_doc);

    IF document IS NOT NULL THEN
        DBMS_OUTPUT.put_line('Document components:');
        DBMS_OUTPUT.put_line('Key: ' || document.get_key);
        DBMS_OUTPUT.put_line('Content: ' ||
                             JSON_QUERY(document.get_blob, '$' PRETTY));
        DBMS_OUTPUT.put_line('Creation timestamp: ' || document.get_created_on);
        DBMS_OUTPUT.put_line('Last modified timestamp: ' ||
                             document.get_last_modified);
        DBMS_OUTPUT.put_line('Version: ' || document.get_version);
    END IF;
END;
/

例3-24 SODA for PL/SQLによる更新(置換)のためのドキュメントのロック

この例では、非ターミナル・メソッドacquire_lock()を使用して、ドキュメントを置換中にロックします。ドキュメントはそのキーによって選択されます。acquire_lock()メソッドはペシミスティック・ロックを提供し、他のユーザーが更新操作を妨げないようにしています。コミットまたはロールバックによりロックが解放されます。この例では、エラーが発生した場合に操作のトランザクションをロールバックします。

DECLARE
  coll    SODA_COLLECTION_T;
  doc1    SODA_DOCUMENT_T;
  doc2    SODA_DOCUMENT_T;
  k       VARCHAR2(255) := 'key-0';
  n       NUMBER;
BEGIN
  coll := DBMS_SODA.open_collection('myCollectionName');

  -- Get the document with a lock, using its key.
  doc1 := coll.find().key(k).acquire_lock().get_One;

  -- Construct a new, replacement document.
  doc2 := SODA_DOCUMENT_T(
    key => k,
    b_content => utl_raw.cast_to_raw('{"name" : "Scott", "age" : 35}'));

  -- Replace the document, specifying its key.
  n := coll.replace_one(k, doc2);

  -- Commit the transaction, releasing the lock.
  COMMIT;
  DBMS_OUTPUT.put_line('Transaction is committed');

-- Catch exceptions and roll back if an error was raised.
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.put_line (SQLERRM);
        ROLLBACK;
        DBMS_OUTPUT.put_line('Transaction has been rolled back');
END;
/

3.13 SODA for PL/SQLによるコレクションからのドキュメントの削除

SODA_OPERATION_Tのメソッドremove()を非ターミナル・メソッドkey()keys()またはfilter()とつないで、削除するドキュメントを識別することにより、コレクションからドキュメントを削除できます。必要に応じて、version()などの追加の非ターミナル・メソッドを使用できます。

ノート:

データ型SODA_OPERATION_Tは、Oracle Database 18.3でSODA for PL/SQLに追加されました。これを使用するにはそのデータベース・リリース以降が必要となります。

関連項目:

  • SODA_COLLECTION_Tのメソッドfind()の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』FINDファンクションに関する項を参照してください

  • データ型SODA_OPERATION_Tとそのメソッドの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』SODA_OPERATION_Tタイプに関する項を参照してください

  • SODA_OPERATION_Tのメソッドremove()の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』REMOVEファンクションに関する項を参照してください

  • SODA_COLLECTION_Tのメソッドremove_one()の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』REMOVE_ONEファンクションに関する項を参照してください

  • SODA_DOCUMENT_Tのgetterメソッドの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』SODA_DOCUMENT_Tタイプに関する項を参照してください

例3-25 ドキュメント・キーによるコレクションからのドキュメントの削除

この例では、ドキュメントのキーが"key1"のドキュメントを削除します。削除ステータス(ドキュメントが削除された場合は1、それ以外の場合は0)が出力されます。

DECLARE
    collection  SODA_COLLECTION_T;
    document    SODA_DOCUMENT_T;
    status      NUMBER;
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Remove document that has key 'key1'
    status := collection.find().key('key1').remove;

    -- Count is 1 if  document was found
    IF status = 1 THEN
        DBMS_OUTPUT.put_line('Document was removed!');
    END IF;
END;
/

例3-26 特定バージョンのドキュメントの削除

ドキュメントを削除する場合にオプティミスティック・ロックを実装するには、この例のようにメソッドkey()およびversion()をつなげることができます。

DECLARE
    collection  SODA_COLLECTION_T;
    document    SODA_DOCUMENT_T;
    status      NUMBER;
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Remove version 'version1' of the document that has key 'key1'.
    status := collection.find().key('key1').version('version1').remove;

    -- Count is 1, if specified version of document with key 'key1' is found
    IF status = 1 THEN
        DBMS_OUTPUT.put_line('Document was removed!');
    END IF;
END;
/

例3-27 ドキュメント・キーによるコレクションからのドキュメントの削除

この例では、キーがkey1key2およびkey3のドキュメントを削除します。

DECLARE
    collection  SODA_COLLECTION_T;
    document    SODA_DOCUMENT_T;
    cur         SODA_CURSOR_T;
    num_docs    NUMBER;
    myKeys      SODA_KEY_LIST_T;
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Define the keys list
    myKeys := SODA_KEY_LIST_T('key1','key2','key3');

    -- Remove documents using keys
    num_docs := collection.find().keys(myKeys).remove;

    DBMS_OUTPUT.put_line('Number of documents removed: ' || num_docs);
END;
/

例3-28 フィルタによるコレクションからのJSONドキュメントの削除

この例では、フィルタを使用してgreetingフィールドの値が"hello"であるJSONドキュメントを削除します。その後、削除されたドキュメントの数を出力します。

DECLARE
    collection  SODA_COLLECTION_T;
    num_docs    NUMBER;
    qbe         VARCHAR2(128);
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Define the filter specification
    qbe := '{ "greeting" : "hello" }';

    -- Get a count of all documents in the collection that match the QBE
    num_docs := collection.find().filter(qbe).remove;
    DBMS_OUTPUT.put_line('Number of documents removed: ' || num_docs);
END;
/

3.14 SODA for PL/SQLによるコレクションの切捨て(すべてのドキュメントの削除)

SODA_COLLECTION_Tのメソッドtruncate()を使用して、コレクションを空にしたり、切り捨ててすべてのドキュメントを削除できます。

例3-29 コレクションの切捨て

この例では、SODA_COLLECTION_Tのメソッドtruncate()を使用して、collectionからすべてのドキュメントを削除します。

DECLARE
    collection SODA_COLLECTION_T;
    document   SODA_DOCUMENT_T;
    status     NUMBER;
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Truncate the collection
    status := collection.truncate;

    -- Count is 1 if  document was found
    IF status = 1 THEN
        DBMS_OUTPUT.put_line('Collection was truncated!');
    END IF;
END;

3.15 SODA for PL/SQLによるコレクション内のドキュメントの索引付け

SODAコレクション内のドキュメントを索引付けするには、SODA_COLLECTION_Tのメソッドcreate_index()を使用します。その入力パラメータはテキストのJSON索引指定です。これにより、Bツリー、空間、全文および非定型の索引付けのサポートを指定し、JSONデータ・ガイドのサポートを指定できます。

ノート:

索引付けに対するSODA for PL/SQLのサポートはOracle Database 18.3で追加されました。このSODA機能を使用するには、そのデータベース・リリース以降が必要となります。

JSON検索索引は、全文問合せおよび非定型構造問合せに使用され、永続的な記録およびJSONデータ・ガイド情報の自動更新に使用されます。

Oracle Spatial and Graph索引はGeoJSON (空間)データに使用されます。

SODAコレクションに対する索引を削除するには、SODA_COLLECTION_Tのメソッドdrop_Index()を使用します。

SODA_COLLECTION_Tのメソッドget_index()またはlist_indexes()をそれぞれ使用して、コレクションの索引指定またはすべての索引指定を取得できます。メソッドlist_indexes()によって返される値は、SODA_INDEX_LIST_Tデータ型のインスタンスで、VARCHAR2索引仕様のPL/SQLコレクションです。

メソッドget_index()には、索引名、およびオプションで関連するデータベース・スキーマ名を引数として指定します。(スキーマおよび索引名に使用される値は、データ・ディクショナリ内の識別子です。特に、大/小文字を同じにする必要があるため、二重引用符を使用せずにSQLで作成した場合は大文字にする必要があります。)

関連項目:

例3-30 SODA for PL/SQLによるJSONフィールドに対するBツリー索引の作成

この例では、コレクションmyCollectionName内のJSONドキュメントの数値フィールドaddress.zipに対して一意ではないBツリー索引を作成しています。

DECLARE
    collection  SODA_COLLECTION_T;
    spec        VARCHAR2(700);
    status      NUMBER;
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Define the index specification
    spec := '{"name"   : "ZIPCODE_IDX",
              "fields" : [{"path"     : "address.zip",
                           "datatype" : "number",
                           "order"    : "asc"}]}';
    -- Create the index
    status := collection.create_index(spec);
    DBMS_OUTPUT.put_Line('Status: ' || status);
END;
/

例3-31 SODA for PL/SQLによるJSON検索索引の作成

この例では、アドホック問合せおよび全文検索(QBE演算子$containsを使用した問合せ)のためにコレクションmyCollectionNameのドキュメントを索引付けし、JSONドキュメントに関するデータ・ガイド情報を自動的に累計および更新します(構造およびタイプ情報を集計します)。索引指定のフィールドはnameのみです(fieldsフィールドは指定しません)。

DECLARE
    collection  SODA_COLLECTION_T;
    spec        VARCHAR2(700);
    status      NUMBER;
BEGIN
    -- Open the collection
    collection := DBMS_SODA.open_collection('myCollectionName');

    -- Define the index specification
    indexSpec := '{"name" : "SEARCH_AND_DATA_GUIDE_IDX"}';
               
    -- Create the index
    status := collection.create_index(indexSpec);
    DBMS_OUTPUT.put_Line('Status: ' || status);
END;
/

ここで使用されている単純な索引指定は、デフォルト値を明示的に使用した次の指定と同じです。

{"name" : "SEARCH_AND_DATA_GUIDE_IDX",
 "dataguide" : "on",
 "search_on" : "text_value"}

かわりに非定型のみ(検索)の索引付けを行う場合は、dataguideフィールドに値"off"を明示的に指定します。かわりにデータ・ガイドのみをサポートする場合は、search_onフィールドに値"none"を明示的に指定します。

ノート:

データ・ガイド対応JSON検索索引を作成する、または既存のJSON検索索引をデータ・ガイド対応にするには、データベース権限CTXAPPおよびOracle Databaseリリース12c (12.2.0.1)以降が必要です。

例3-32 SODA for PL/SQLによる索引の削除

この例では、SODA_COLLECTION_Tのメソッドdrop_index()を使用して、コレクションmyCollectionName上の索引myIndexを削除します。

DECLARE
    coll    SODA_COLLECTION_T;
    status  NUMBER;
BEGIN
    -- Open the collection
    coll := dbms_soda.open_Collection('myCollectionName');

    -- Drop the index using name
    status := coll.drop_index('myIndex');
    DBMS_OUTPUT.put_Line('Status: ' || status);
END;
/

例3-33 SODA for PL/SQLによる索引指定の取得

この例では、メソッドget_index()を使用して、コレクションmyCollectionNameのドキュメントに対するデータベース・スキーマ(ユーザー名)MY_SCHEMAZIPCODE_IDXという名前の索引を定義するために使用される指定を取得します。これらの各名前は、データ・ディクショナリに表示されるように記述する必要があります。

DECLARE
  spec    VARCHAR2(1000);
  coll    SODA_Collection_T;
BEGIN
  coll := DBMS_SODA.open_collection('myCollectionName');
  spec := coll.get_index('ZIPCODE_IDX', 'MY_SCHEMA');
  DBMS_OUTPUT.put_line(json_query(spec, '$' pretty));
END;
/

例3-34 SODA for PL/SQLによるコレクションのすべての索引指定の取得

この例では、メソッドlist_indexes()を使用して、コレクションmyCollectionNameのドキュメントに定義されているすべての索引指定を変数idxで取得します。次に、件数も一緒に出力します(データ型SODA_INDEX_LIST_Tのメソッドcountを使用して取得)。

DECLARE
  coll    SODA_COLLECTION_T;
  idx     SODA_INDEX_LIST_T;
BEGIN
  coll := DBMS_SODA.open_collection('myCollectionName');
  idx := coll.list_indexes;
  DBMS_OUTPUT.put_line('Number of indexes: ' || idx.COUNT);

  if (idx.COUNT <> 0) then
    for i in idx.FIRST..idx.LAST
    loop
      DBMS_OUTPUT.put_line('Index ' || i || ': ');
      DBMS_OUTPUT.put_line(json_query(idx(i), '$' pretty));
    end loop;
  else
    DBMS_OUTPUT.put_line('No indexes defined on this collection');
  end if;
END;
/

3.16 SODA for PL/SQLによるコレクションのデータ・ガイドの取得

SODA_COLLECTION_Tのメソッドget_data_guide()またはターミナルSODA_OPERATION_Tのメソッドget_data_guide()を使用して、コレクションのデータ・ガイドを取得できます。データ・ガイドは、コレクション内のJSONドキュメントの構造およびタイプ情報をまとめたJSONドキュメントです。これらの文書内で使用されているフィールドに関するメタデータを記録します。

ノート:

JSONデータ・ガイドに対するSODA for PL/SQLのサポートは、Oracle Database 18.3で追加されました。このSODA機能を使用するには、そのデータベース・リリース以降が必要となります。

コレクションのデータ・ガイドを作成するには、get_data_guide()という2つの異なるメソッドを使用します。

  • ターミナルSODA_OPERATION_Tのメソッドget_data_guide()を、操作sample()または例による問合せ(QBE)のfilter()操作とともに使用します。これにより、問合せによって選択されたドキュメント専用のデータ・ガイドが最初から動的に作成されます。このように、ドキュメントのセットを制限して、これをデータ・ガイドのベースにできます。例3-35に、これを示します。

    (この方法は、SQLファンクションjson_dataguideの使用に対応しています。)

  • SODA_COLLECTION_Tのメソッドget_data_guide()を使用します。これにより常に、コレクション内のすべてのドキュメントに基づいてデータ・ガイドが作成されます。例3-36に、これを示します。

    このメソッドでは、JSON検索索引の一部として格納されている永続データ・ガイド情報を使用するため、このメソッドを使用する前に、まずコレクションにデータ・ガイド対応のJSON検索索引を作成する必要があります。この方法を例3-31に示します。索引内のデータ・ガイド情報は永続的であり、新しいJSONコンテンツが追加されると自動的に更新されます。

    (このメソッドは、PL/SQLファンクションget_index_dataguideの使用に対応しています。)

索引ベースのSODA_COLLECTION_Tメソッドでは、ドキュメント書込み(作成および更新)に伴う索引更新など、関連データを永続的に更新する継続的なコストが発生します。ただし、データ・ガイド情報は索引ですぐに使用できるため、データ・ガイド・ドキュメントを生成するときに最初から収集する必要はありません。

SODA_OPERATION_Tメソッドは毎回最初から開始されるため、一般的な使用には、ドキュメントのランダムなサンプルにのみメソッドを適用したり、一部のフィルタ(QBE)を満たすドキュメントにのみメソッドを適用することが含まれます。例3-35に示すように、SODA_OPERATION_Tのメソッドsample()を使用してランダムなサンプルを取得できます。

関連項目:

  • 『Oracle Database JSON開発者ガイド』JSONデータ・ガイドに関する項を参照してください

  • タイプSODA_OPERATION_Tについては、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』GET_DATA_GUIDEファンクションに関する項を参照してください

  • タイプSODA_COLLECTION_Tについては、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』GET_DATA_GUIDEファンクションに関する項を参照してください

  • SQLを使用したデータのサンプルの選択の詳細は、『Oracle Database SQL言語リファレンス』SELECT文、sample_clauseに関する項を参照してください

例3-35 SODA for PL/SQLによるデータ・ガイドの動的な作成

この例では、SODA_OPERATION_Tのターミナル・メソッドget_data_guide()を非ターミナル操作sample()脚注1とともに使用して、コレクションMyCollectionNameのドキュメントのランダムなサンプルのデータ・ガイドを取得します。サンプルに含まれる特定のドキュメントの割合は40%です(引数値40)。

この例では、フラット形式でデータ・ガイド・ドキュメントのコンテンツを整形出力します。最後に、データ・ガイド・ドキュメントに使用されている一時LOBが解放されます。

操作sample()は、読取り操作にのみ使用します。書込み操作では無視されます。動的データ・ガイドの作成は、sample()の一般的なユースケースです。また、SODA_OPERATION_Tのターミナル・メソッドget_cursor()とともに使用することもできます。

ランダムなサンプルを使用する以外に、動的に作成されたデータ・ガイドによって表されるドキュメントを制限するもう1つの一般的な方法は、操作sample()のかわりに例による問合せ(QBE) filter()操作を使用することです。

DECLARE
    coll         SODA_COLLECTION_T;
    qbe          VARCHAR2(100);
    dataguide    CLOB;
    dgflag       PLS_INTEGER;
    dgformat     PLS_INTEGER;
BEGIN
    -- Open the collection.
    coll := DBMS_SODA.open_Collection('myCollectionName');

    dgflag   := DBMS_SODA.DATAGUIDE_PRETTY;
    dgformat := DBMS_SODA.DATAGUIDE_FORMAT_FLAT;

    -- Get dynamic data guide for the collection.
    dataguide := coll.find().sample(40).get_data_guide(flag   => dgflag,
                                                       format => dgformat);
    DBMS_OUTPUT.put_line(dataguide);

    -- Important: Free the temporary LOB.
    IF DBMS_LOB.isTemporary(dataguide) = 1
    THEN
        DBMS_LOB.freeTemporary(dataguide);
    end if;   
END;
/

関連項目:

例3-36 SODA for PL/SQLによるJSON検索索引を使用したデータ・ガイドの作成

この例では、SODA_COLLECTION_Tのメソッドget_data_guide()を使用して、コレクションMyCollectionName内のすべてのドキュメントのデータ・ガイドを取得します。このメソッドを使用するには、データ・ガイド対応JSON検索索引がコレクションに定義されている必要があります。

この例では、SQL/JSONファンクションjson_queryを使用して、データ・ガイド・ドキュメントのコンテンツを整形出力します。最後に、データ・ガイド・ドキュメントに使用されている一時LOBが解放されます。

DECLARE
    collection SODA_COLLECTION_T;
    dataguide  CLOB;
BEGIN
    -- Open the collection.
    collection := DBMS_SODA.open_Collection('myCollectionName');
    
    -- Get the data guide for the collection.
    dataguide := collection.get_data_guide;
    DBMS_OUTPUT.put_line(json_query(dataguide, '$' pretty));
    
    -- Important: Free the temporary LOB.
    IF DBMS_LOB.isTemporary(dataguide) = 1
    THEN
        DBMS_LOB.freeTemporary(dataguide);
    end if;   
END;
/

3.17 SODA for PL/SQLによるデータ・ガイドからのビューの作成

SODA_COLLECTION_Tのメソッドcreate_view_from_dg()を使用して、リレーショナル列を含むデータベース・ビューを作成できます。このビューの名前および値は、データ・ガイドで指定されたスカラーJSONフィールドから取得されます。これには、データ・ガイド対応のJSON検索索引は必要ありません。データ・ガイド自体はメソッドに渡されます。

例3-37 SODA for PL/SQLによるJSONデータ・ガイドからのリレーショナル・ビューの作成

この例では、例3-36のように、コレクションのJSONデータ・ガイドを取得して整形出力します。次に、create_view_from_dg()を使用して、データ・ガイドのスカラーJSONフィールドに基づく列を含むリレーショナル・ビューを作成します。最後に、データ・ガイド・ドキュメントに使用されている一時LOBが解放されます。

DECLARE
    coll  SODA_COLLECTION_T;
    dg    CLOB;
    n     NUMBER;
BEGIN
    -- Open a collection
    coll := DBMS_SODA.open_collection('myCollectionName');
    
    -- Get and print the data guide for the collection
    dg := coll.get_data_guide;
    DBMS_OUTPUT.put_line(json_query(dg, '$' pretty));
    
    -- Create view from data guide
    n = coll.create_view_from_dg('MY_VIEW_FROM_DG', dg);
    
    -- Free the temporary LOB containing the data guide
    if DBMS_LOB.isTemporary(dg) = 1
    then
      DBMS_LOB.freeTemporary(dg);
    end if;   
END;

3.18 SODA for PL/SQLによるトランザクションの処理

通常のPL/SQLやSQLのように、個別のSODA読取りおよび書込み操作(または、それらの操作のグループ)をトランザクションとして処理できます。トランザクションをコミットするには、SQL COMMIT文を使用します。変更をロールバックする場合は、SQL ROLLBACK文を使用します。

SODA操作のDBMS_SODA.create_collectionDBMS_SODA.drop_collectionでは、そのアクションの実行前後に自動的にコミットされません。これは、アクションの実行前後にコミットするSQL DDL文の動作とは異なります。

この結果の1つとして、SODAコレクションの削除前には、未処理の書込み操作を明示的にコミットするかロールバックする必要があります。そのために、明示的にSQL COMMITまたはROLLBACKを使用する必要があります。その理由は、DBMS_SODA.drop_collectionはアクションの実行前にコミットを発行しないためです。この点で、DBMS_SODA.drop_collectionの動作はSQL DROP TABLE文の動作と異なります。

関連項目:

  • SQL COMMIT文の詳細は、『Oracle Database SQL言語リファレンス』COMMITに関する項を参照してください

  • SQL ROLLBACK文の詳細は、『Oracle Database SQL言語リファレンス』ROLLBACKに関する項を参照してください

  • SODA_COLLECTION_Tのメソッドinsert_one()の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』SODA_COLLECTION_Tタイプに関する項を参照してください

例3-38 SODAドキュメントの挿入と置換に関連するトランザクション

この例は、無名PL/SQLブロック内で使用しているSQL COMMIT文およびROLLBACK文を示しています。ここでは、SODAコレクションを開いて、ドキュメントを挿入してから、そのコンテンツを置換します。ドキュメントの挿入操作とドキュメント・コンテンツの置換操作の組合せはアトミックです(つまり、単一のトランザクションです)。

DECLARE
    collection SODA_COLLECTION_T;
    status NUMBER;
BEGIN
    collection := DBMS_SODA.open_collection('myCollectionName');
    status := collection.insert_one(
                SODA_Document_T(
                  b_content => utl_raw.cast_to_raw('{"a":"aval", "b":"bval", "c":"cval"}')));
    status := collection.replace_one(
                'key1',
                SODA_DOCUMENT_T(
                  b_content => utl_raw.cast_to_raw('{"x":"xval", "y":"yval"}')));
    -- Commit the transaction
    COMMIT;
    DBMS_OUTPUT.put_line('Transaction is committed');
-- Catch exceptions and roll back if an error is raised
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.put_line (SQLERRM);
    ROLLBACK;
    DBMS_OUTPUT.put_line('Transaction has been rolled back');
END;
/


脚注の凡例

脚注1: 操作sample()は、SQL SELECT文のsample_clauseに対応しています。