5.4 二面性ビューでのオプティミスティックな同時実行性制御の使用

他のセッションで同時に変更されていない場合にのみ、二面性ビューでのオプティミスティック/ロックフリーの同時実行性制御の使用、JSONドキュメントの記述、または更新のコミットを実行できます。

ドキュメント・レベルでのオプティミスティック同時実行性制御では、フィールド_metadataの値であるオブジェクト内のフィールドetagに埋込みETAG値が使用されます。

ノート:

特に明示的に示されていないかぎり、次のようになります。

  • ここに示す例は、決して相互に依存するものではありません。特に、それらの間には暗黙的な順序付けはありません。

  • ここでの二面性ビューを使用する例では、「二面性ビューの作成」で定義したビューを使用します。これらのビューは、UNNESTを使用して定義されています(例3-1例3-3および例3-5)。

  • ここでの表を使用する例では、「カーレースの例、表」で定義した表を使用します。

ドキュメント中心のアプリケーションでは、オプティミスティックな同時実行性制御の使用により、更新が失われることを防止する場合があります。つまり、複数のデータベース・セッションがある場合はそれらで共通使用されているデータが変更されることで互いに妨げになるという問題への対処です。

ドキュメントのオプティミスティック同時実行性は、変更したドキュメントを保持(書込み)しようとすると、現在保持されているドキュメント・コンテンツが、必要な変更の適用先(ローカル)のコンテンツに対してチェックされるという考えに基づいています。つまり、コンテンツの現在の永続状態/バージョンは、最後の読取りとして永続コンテンツのアプリケーションのレコードと比較されます。

2つが異なる場合は、最後の読取りコンテンツが失効していることを意味します。次に、アプリケーションは最後に永続化されたコンテンツを取得し、それを変更の新しい開始点として使用し、新しく変更されたドキュメントを書き込もうとします。書込みは、アプリケーションによって最後に読み取られたコンテンツが、現在永続化されているコンテンツと同じ場合にのみ成功します。

この方法では、一般的に高いレベルの同時実行性を実現し、対話型アプリケーション(人間の待機時間なし)、切断されたモバイル・アプリケーション(古いドキュメントを使用した書込み試行は取り消されます)およびドキュメント・キャッシュ(古いキャッシュを使用した書込み試行は取り消されます)の利点がもたらされます。

同じデータに対する同時データベース操作の可能性が低いほど、オプティミスティックな同時実行性の効率が向上します。同じデータに多数の競合がある場合は、異なる同時実行性制御技術を使用する必要がある場合があります。

簡潔に述べると、オプティミスティックな同時実行性を実装するためにアプリケーション・コードで使用する手法は次のようになります。

  1. 変更するデータを読み取ります。その読取りから、そのデータの未変更の状態(その永続的な、最終コミット後の状態)のローカル表現を記録します。

  2. そのデータのローカル・コピーを変更します。

  3. 現在の永続状態が、記録されている状態と同じである場合のみ、変更されたデータを書き込みますます(永続化します)。

つまり、変更を永続化するまで、そのデータを未変更の状態のままにします。最後の読取り以降にそのデータが変更された場合は、再度、ステップ1から3を繰り返します

二重ビューでサポートされているJSONドキュメントの場合は、トップレベル・フィールド_metadataの値であるオブジェクト内のドキュメントのetagフィールドを確認することでこれを実行します。

フィールドetagのETAG値は、オプティミスティックな同時実行性制御のために確認するドキュメント・コンテンツを記録します。

デフォルトでは、ドキュメント・コンテンツ自体(ペイロード)のすべてが含まれます。フィールド_metadata (フィールドetagを含む値)はペイロードの一部ではなく、ETAG計算から常に除外されます。

フィールドmetadataに加えて、ETAG計算から選択したペイロード・フィールドを除外できます。これは、同時実行性制御にとって変更が重要でないデータです。そのデータが最後にアプリケーションによって読み取られてから変更されても、更新操作は妨げられません。(リレーショナルな表現では、これは、ロックされている行内の特定の列をロックしないことに似ています。)

二面性ビュー定義のNOCHECK注釈で管理される列に対応するドキュメント・コンテンツは、そのビューでサポートされるドキュメントのETAG値の計算に関与しません。その他の内容はすべて計算に関与します。ETAG値は、CHECKとマークされた(暗黙的または明示的に)基礎となる表の列のみに基づきます。「注釈(NO)CHECKによるETAG計算のフィールドの包含/除外」を参照してください。

次に、フィールド_metadataとそのetagフィールド、ドキュメント・ペイロードが表示されたレース・ドキュメントの例を示します。ドキュメント・メタデータの詳細は、「二面性ビューの作成」を参照してください。

{"_metadata" : {"etag" : "E43B9872FC26C6BB74922C74F7EF73DC",
                         "asof" : "00000000000C20BA"},
 "_id" : 201, "name" : "Bahrain Grand Prix", ...}

したがって、Oracle ETAGの同時実行性制御は値ベースまたはコンテンツベースです。競合する更新は、実際に、データの内容そのものを調べることで検出されます。

  • 読取り/取得操作によって自動的にフィールドetagが更新されます。これにより、CHECK可能なドキュメント・コンテンツの現在の永続状態がHTTP ETAGハッシュ値として記録されます。

  • ドキュメントのetag値が現在の永続(最終コミット後)データのその値と一致しない場合は、書込み/入力操作で自動的にドキュメントが拒否されます。つまり、そのデータが最後の読取り以降に変更されていた場合は、Oracle Databaseでエラーが発生します。そのため、アプリケーションで必要なのは、書込みエラーがあるかチェックして、ステップ1から3を繰り返すかどうかを判断することのみです。

図5-1にこのプロセスを示します。

図5-1 オプティミスティック同時実行性制御プロセス

図5-1の説明は図の下のリンクをクリックしてください。
「図5-1 オプティミスティック同時実行性制御プロセス」の説明

実際の永続データ/内容に対する同時実行性の制御をベースにすると、ドキュメント・バージョン番号やタイムスタンプなどのロックまたはサロゲート情報を使用するよりも強力になり、信頼性が高くなります。

Oracle ETAGは値ベースであるため、様々なドキュメントのデータに対する更新が自動的に同期されます。また、ドキュメントの更新と基礎となる表への直接更新の間で同時実行性を自動的に確保します。ドキュメントAPIとSQLアプリケーションは、同じデータを同時に更新できます。

ステップ2 (ローカルで変更)とステップ3 (書込み)は実際に結合しています。更新操作の変更済ドキュメントを指定する場合、変更済ドキュメントのetagフィールドの値として読取り操作によって返されるETAG値を含めます。

データベース内のドキュメントの現在のコンテンツがetagフィールド値と異なる場合、試行された更新操作は失敗します。これは、最後の読取り以降にデータベース内のドキュメントが変更されたことを意味するためです。その操作に失敗した場合は、もう一度試してください。再度読み取って最新のETAG値を取得してから、フィールドetag内のETAG値を使用して更新を再試行します。

たとえば、次のように、Bahrain Grand Prix (_id=201)という名前のレースについて、2つの異なるデータベース・セッション(S1およびS2)が同じドキュメントを同時に更新するとします。

  • セッションS1は、例5-8または例5-9の更新を実行し、レース結果(フィールドlapsdatepodiumおよびresults)を書き込みます。

  • セッションS2は、例5-10の更新を実行し、レースの名前をBlue Air Bahrain Grand Prixに変更します。

各セッションは、更新操作にオプティミスティックな同時実行性を使用し、更新操作(ステップ2)が成功するまで次の2つのステップを繰り返し、変更をCOMMITすることにより、変更内容が最新のドキュメント・コンテンツであることを保証します。

  1. ドキュメントを読み取ります(選択します)。取得されたドキュメントのフィールドetagの値は、データベース内のドキュメントの現在の(CHECK可能な)コンテンツをエンコードします。

    例5-15および例5-16に、これを示します。

  2. 変更した内容を使用し、ステップ1で取得したフィールドetagを使用して、ドキュメントの更新を試みます。

    セッションS1の場合、更新操作は例5-8または例5-9です。セッションS2の場合、例5-10です。

ETAG値がドキュメントの現在の永続(最後にコミットされた)状態と一致しないため、更新操作に失敗すると、エラーが発生します。

このようなSQLからのエラーの例を次に示します:

UPDATE race_dv
*
ERROR at line 1:
ORA-42699: Cannot update JSON Relational Duality View 'RACE_DV': The ETAG of
document with ID 'FB03C2030200' in the database did not match the ETAG passed
in.

このようなRESTからのエラーの例を次に示します。If-Matchヘッダーに指定されたETAG値が、レース・ドキュメントのものと同じではありませんでした。

Response: 412 Precondition Failed

{"code"     : "PredconditionFailed",
 "message"  : "Predcondition Failed",
 "type"     : "tag:oracle.com,2020:error/PredconditionFailed",
 "instance" : "tag:oracle.com,2020:ecid/y2TAT5WW9pLZDNu1icwHKA"}

同じ基礎となる表データに対応する内容を持つ2つのドキュメントに対して複数の操作が同時に処理され、その内容がそのドキュメントのETAG計算に関与する場合、その操作の1つは成功する可能性があります。このため、同じ基礎となるデータを同時に変更しようとすると、必ずエラーが発生します。エラー・メッセージは、競合する操作が検出されたことを示し、可能な場合は、競合が検出されたドキュメント・フィールドを示します。

JSONリレーショナル二面性とは、ETAGをデータとともに使用して、SQLを使用したロックフリーな行の更新を実行することもできるということです。これを実行するには、ファンクションSYS_ROW_ETAGを使用して、表行の特定の列セットの現在の状態をETAGハッシュ値として取得します。

ファンクションSYS_ROW_ETAGは、行の指定された列の値のみを使用して行のETAG値を計算します。他のセッションが同時に更新しないようにする、すべての列の名前を渡します。これには、現在のセッションが更新する予定の列も含まれていますが、更新操作がアプリケーションに対して論理的に依存する値を含む列も含まれています。(引数として列をSYS_ROW_ETAGに渡す順序は関係ありません。)

この例では、S3およびS4という2つの異なるデータベース・セッションが、_idが201のレースに対して同じrace表データを同時に更新することを想定しています:

  • セッションS3は、列podiumを更新して、レースのpodium値を公開しようとします。

  • セッションS4は、列nameを更新し、レースの名前をBlue Air Bahrain Grand Prixに変更しようとします。

セッションは、オプティミスティックな同時実行性制御を使用して、干渉なしで特定の行を更新できます。そのため、(1)更新する行の現在のETAG値を取得し、(2)更新を試行し、そのETAG値を渡します。操作が失敗した場合、これらのステップを繰り返します。更新が成功するまで、新しいETAG値で再試行します(この時点で更新がコミットされます)。

例5-15 フィールドetagからのレース・ドキュメントの現在のETAG値の取得 — SQLの使用

この例では、_id 201のレースのドキュメントを選択します。ネイティブ・バイナリのJSON型データをテキストにシリアライズし、これを整形出力します。上位レベルのフィールド_metadataの値であるオブジェクトのフィールドetagのETAG値は、ドキュメントの現在のコンテンツをエンコードします。

そのetagフィールドと、更新操作に指定する変更済ドキュメントの値を使用します。

SELECT json_serialize(DATA PRETTY)
  FROM race_dv WHERE json_value(DATA, '$._id.numberOnly()') = 201;
JSON_SERIALIZE(DATAPRETTY)
--------------------------
{ 
  "_metadata" :
  { "etag" : "E43B9872FC26C6BB74922C74F7EF73DC",
    "asof" : "00000000000C20BA"
  },
  "_id" : 201,
  "name" : "Bahrain Grand Prix",
  "laps" : 57,
  "date" : "2022-03-20T00:00:00",
  "podium" :
  {
  },
  "result" :
  [
  ]
}
1 row selected.

例5-16 フィールドetagからのレース・ドキュメントの現在のETAG値の取得 — RESTの使用

この例では、Oracle REST Data Services (ORDS)を使用して例5-15と同じことを実行します。二面性ビューの例を所有するデータベース・ユーザー(スキーマ)は、ここではユーザーJANUSとして表示されます。

curl --request GET \
  --url http://localhost:8080/ords/janus/race_dv/201

Response:

{"_id"    : 201,
 "name"      : "Bahrain Grand Prix",
 "laps"      : 57,
 "date"      : "2022-03-20T00:00:00",
 ...
 "_metadata" : {"etag": "20F7D9F0C69AC5F959DCA819F9116848",
                "asof": "0000000000000000"},
 "links"     : [ {"rel": "self",
                  "href": "http://localhost:8080/ords/janus/race_dv/201"},
                 {"rel": "describedby",
                  "href": "http://localhost:8080/ords/janus/metadata-catalog/race_dv/item"},
                 {"rel": "collection",
                  "href": "http://localhost:8080/ords/janus/race_dv/"} ]}

ノート:

最適なパフォーマンスを得るには、Oracle REST Data Services (ORDS)を構成して、1秒のタイムアウトを指定してメタデータ・キャッシュを有効にしにます:

cache.metadata.enabled = true
cache.metadata.timeout = 1

『Oracle REST Data Servicesインストレーションおよび構成ガイド』の「REST対応SQLサービス設定の構成」を参照してください。

例5-17 ファンクションSYS_ROW_ETAGを使用した、表の同時更新の最適な制御

2つのデータベース・セッション(S3およびS4)は、表raceの同じ行(列race_idの値が201である行)を更新しようとします。

簡素化のために、ここではセッションS3に対してのみオプティミスティックな同時実行性制御を示します。セッションS4では、列nameの更新操作のみを示しています。

このシナリオでは、次のようになります:

  1. セッションS3は、列namerace_dateおよびpodiumをファンクションSYS_ROW_ETAGに渡し、(なんらかの理由で)列podiumの更新中に、S3で、他のセッションがnamerace_dateおよびpodiumのいずれの列も変更しないようにすることを想定しています。

  2. セッションS4は、列nameを更新し、その更新をコミットします。

  3. S3は、取得したETAG値を渡して、列podiumを更新しようとします。S4が同じ行の更新のため、この試行は失敗します。

  4. S3は、新しいETAG値を使用して行の更新を再試行します。この試行は成功し、S3が変更をコミットします。

-- S3 gets ETAG based on columns name, race_date, and podium.
SELECT SYS_ROW_ETAG(name, race_date, podium)
  FROM race WHERE race_id = 201;
SYS_ROW_ETAG(NAME,RACE_DATE,PODIUM)
-----------------------------------
201FC3BA2EA5E94AA7D44D958873039D
-- S4 successfully updates column name of the same row.
UPDATE race SET name = 'Blue Air Bahrain Grand Prix'
  WHERE race_id = 201;
1 row updated.
-- S3 unsuccessfully tries to update column podium.
--    It passes the ETAG value, to ensure it's OK to update.
UPDATE race SET podium = 
                '{"winner"         : {"name" : "Charles Leclerc",
                                      "time" : "01:37:33.584"},
                  "firstRunnerUp"  : {"name" : "Carlos Sainz Jr",
                                      "time" : "01:37:39.182"},
                  "secondRunnerUp" : {"name" : "Lewis Hamilton",
                                      "time" : "01:37:43.259"}}'
  WHERE race_id = 201
    AND SYS_ROW_ETAG(name, race_date, podium) =
          '201FC3BA2EA5E94AA7D44D958873039D';
0 rows updated.
-- S4 commits its update.
COMMIT;
Commit complete.
-- S3 gets a fresh ETAG value, and then tries again to update.
SELECT SYS_ROW_ETAG(name, race_date, podium)
  FROM race WHERE race_id = 201;
SYS_ROW_ETAG(NAME,RACE_DATE,PODIUM)
-----------------------------------
E847D5225C7F7024A25A0B53A275642A
UPDATE race SET podium = 
                '{"winner"         : {"name" : "Charles Leclerc",
                                      "time" : "01:37:33.584"},
                  "firstRunnerUp"  : {"name" : "Carlos Sainz Jr",
                                      "time" : "01:37:39.182"},
                  "secondRunnerUp" : {"name" : "Lewis Hamilton",
                                      "time" : "01:37:43.259"}}'
  WHERE race_id = 201
    AND SYS_ROW_ETAG(name, race_date, podium) =
          'E847D5225C7F7024A25A0B53A275642A';
1 row updated.
COMMIT;
Commit complete.

-- The data now reflects S4's name update and S3's podium update.
SELECT name, race_date, podium FROM race WHERE race_id = 201;
NAME   RACE_DATE   PODIUM
-------------------------
Blue Air Bahrain Grand Prix
20-MAR-22
{"winner":{"name":"Charles Leclerc","time":"01:37:33.584"},"firstRunnerUp":{"nam
e":"Carlos Sainz Jr","time":"01:37:39.182"},"secondRunnerUp":{"name":"Lewis Hami
lton","time":"01:37:43.259"}}

1 row selected.

_________________________________________________________

関連項目:

『Oracle REST Data Services開発者ガイド』JSONリレーショナル二面性ビューのサポート

5.4.1 二面性ビューのトランザクションの使用

JSONドキュメントで連続する複数の更新(DML)操作に対するオプティミスティックな同時実行性制御を実現するために、二面性ビューに固有の特別な種類のトランザクションを使用できます。一連の更新をコミットするのは、他のセッションが同じドキュメントを同時に変更していない場合のみです。

「二面性ビューでのオプティミスティックな同時実行性制御の使用」では、ドキュメントのETAG値を使用して、単一の更新(DML)操作に対する同時実行性を最適に制御する方法について説明します。

ただし、複数の更新をユニットとしてまとめて実行する場合、更新済ドキュメントの未変更部分を更新間で、別のセッションで変更しない、つまりコミットする前に、変更しないようにするにはどうすればよいでしょうか。

これを実行する1つの方法として、複数の更新操作の間、1つ以上の二面性ビューで1つ以上のドキュメントをロックします。これを実行するには、ビューからJSON型の列DATAの対応する行をSELECTしてFOR UPDATEを実行します。例5-18に、これを示します。ただし、これを実行すると、基礎となる表のそれぞれがロックされ、負荷がかかる場合があります。

かわりに、二面性ビュー固有の特別な種類のトランザクションを使用して、二面性ビュー・ドキュメントに対して複数の更新操作を最適に実行できます。実際は、ドキュメント(ビューのDATA列の行)が完全にロックされているが、ロックされていないように見えます。ロックは、変更される基礎となる表の行に対してのみ実行され、変更されていない行はトランザクション全体でロックされていないままになります。変更は、ドキュメントが同時に変更されていない場合にのみコミットされます。

もう1つの同時セッションで更新間でドキュメントを変更できますが、トランザクションがコミットされる前にそれが発生した場合はコミット操作が失敗し、その場合は再試行します。

二面性ビューのトランザクションでは、読取りが繰り返し行われます。トランザクション実行中のすべての読取りは、トランザクションの開始時に取得されるデータのスナップショットに対して実行されます。

トランザクション内で、更新操作の前に、更新する予定の各ドキュメントが、データベース内の現在保持されている値に関して最新であることを確認します。この検証は、ドキュメントの登録と呼ばれます。ドキュメントを登録すると、ドキュメントを読み取って取得したETAG値が最新であることが検証されます。この検証に失敗した場合は、トランザクションをロールバックしてやりなおします。

二面性ビューに対して複数操作トランザクションを実行するには、パッケージDBMS_JSON_DUALITYから次のプロシージャを使用してPL/SQLコードを使用します:

  • begin_transaction - トランザクションを開始します。これにより、データベースの状態の"スナップショット"が効率的に取得されます。トランザクションのすべての更新操作は、このスナップショットに基づきます。

  • register - 最後の読取りとしてドキュメントのETAG値が、トランザクションの開始時にデータベース内のドキュメントのETAG値と一致することを確認します。そうでない場合は、エラーが発生します。つまり、ドキュメントの更新時に使用するETAG値がトランザクションの開始時点で正しいことを確認してください。

    最後にドキュメントを読み取り、そのETAG値をトランザクションの開始前に取得した場合、その値はトランザクションに対して必ずしも有効ではありません。コミット操作は、トランザクションの開始前に発生した可能性のある変更をチェックできません。トランザクションの開始前にドキュメントを最後に読み取った場合は、registerをコールして、ドキュメントに使用するETAG値が最初から有効であることを確認します。

    プロシージャregisterは、オブジェクト識別子(OID)を使用してチェックするドキュメントを識別します。これは、二面性ビューの非表示列RESIDを問い合せることで取得できます。ドキュメントを読み取ってETAG値を取得するかわりに、二面性ビューの非表示列ETAGを問い合せることができます。

  • commit_transaction - 複数の更新トランザクションをコミットします。ETAG値を比較して、更新用に指定されたドキュメントをデータベースの現在の状態に対して検証します。更新のために発行されたドキュメントのETAGが、トランザクション中に同時セッションによって変更された場合は、エラーが発生します。

プロシージャは、begin_transactionregistercommit_transactionの順にコールします。begin_transactionをコールした直後にregisterをコールします。

全体的なアプローチは、1つの更新操作で使用するのと同じですが、複数の操作にわたって拡張されます。データベース内のドキュメントを最適に変更し、一部の同時操作が妨げられた場合は、最初からやりなおして新しいトランザクションを再試行します。

  1. トランザクション中にいずれかが失敗した場合(エラーが発生した場合)、これをロールバック(ROLLBACK)し、新しいトランザクションを開始してbegin_transactionを再度コールします。

    特に、ドキュメント登録が失敗した場合やトランザクションのコミットに失敗した場合は、新しいトランザクションでやりなおす必要があります。

  2. 新しいトランザクションの開始時に、ドキュメントを再度読み、トランザクションの開始時のデータベース状態のETAG値を取得して、registerを再度コールします。

エラーがなくなるまでステップ1と2を繰り返します。

例5-18 更新のための二面性ビュー・ドキュメントのロック

この例では、二面性ビューteam_dvの生成されたJSON型のDATA列のMercedesおよびFerrariチーム行を、現在のセッションの次のCOMMITまでロックします。

FOR UPDATE句は、列DATAの行全体をロックします。これは、チーム・ドキュメント全体をロックすることを意味します。これは、同様に、基礎となる各表の関連行をロックすることを意味します。

SELECT DATA FROM team_dv dv
  WHERE dv.DATA.name LIKE 'Mercedes%'
  FOR UPDATE;

SELECT DATA FROM team_dv dv
  WHERE dv.DATA.name LIKE 'Ferrari%'
  FOR UPDATE;

関連項目:

例5-19 二面性ビューのトランザクションを使用した、2つのドキュメントの適切な同時更新

この例では、二面性ビューのトランザクションでのオプティミスティックな同時実行性を使用して、チームMercedesおよびFerrariの二面性ビューteam_dvのドキュメントを更新します。ここでは、2チーム間でドライバのCharles LeclercとGeorge Russellを入れ替えます。トランザクション後、チーム・ドキュメント(二面性ビューteam_dvでサポート)とドライバ・ドキュメント(二面性ビューdriver_dvでサポート)の両方がドライバの入替えを反映します。

ドキュメントを読み取って、ドキュメント識別子(非表示の列RESID)および現在のETAG値を取得します。ETAG値は、取得したドキュメントでメタデータ・フィールドetagの値としてここで取得されますが、かわりに非表示列ETAGを選択することも可能です。

SELECT RESID, DATA FROM team_dv dv
  WHERE dv.DATA.name LIKE 'Mercedes%';
RESID
-----
DATA
----
FB03C2040400
{"_id" : 303,
 "_metadata":
  {"etag" : "039A7874ACEE6B6709E06E42E4DC6355",
   "asof" : "00000000001BE239"},
 "name" : "Mercedes",
 ...}
SELECT RESID, DATA FROM team_dv dv
  WHERE dv.DATA.name LIKE 'Ferrari%';
RESID
-----
DATA
----
FB03C2040300
{"_id" : 303,
 "_metadata":
  {"etag" : "C5DD30F04DA1A6A390BFAB12B7D4F700",
   "asof" : "00000000001BE239"},
 "name" : "Ferrari",
 ...}

複数の更新トランザクションを開始してから、更新する各ドキュメントを登録し、前回読み取ってから変更されていないことを確認します。前述で読み取ったドキュメントIDおよびETAGの値は、プロシージャregisterに渡されます。

ETAGが最新でない場合、他のセッションで読取りとトランザクション開始の間にドキュメントが更新されたため、ROLLBACKが必要になり、その後begin_transactionでやりなおします(ここには示されていません)。

BEGIN
  DBMS_JSON_DUALITY.begin_transaction();
  DBMS_JSON_DUALITY.register('team_dv',
                             hextoraw('FB03C2040400'),
                             hextoraw('039A7874ACEE6B6709E06E42E4DC6355'));
  DBMS_JSON_DUALITY.register('team_dv',
                             hextoraw('FB03C2040300'),
                             hextoraw('C5DD30F04DA1A6A390BFAB12B7D4F700'));

更新(DML)操作を実行します: ドライバを入れ替えたドキュメントに元のドキュメントを置き換えます。

  UPDATE team_dv dv
    SET DATA = ('{"_id" : 303,
                  "name"   : "Mercedes",
                  "points" : 40,
                  "driver" : [ {"driverId" : 106,
                                "name"     : "Lewis Hamilton",
                                "points"   : 15},
                               {"driverId" : 103,
                                "name"     : "Charles Leclerc",
                                "points"   : 25} ]}')
      WHERE dv.DATA.name LIKE 'Mercedes%';

  UPDATE team_dv dv
    SET DATA = ('{"_id" : 302,
                  "name"   : "Ferrari",
                  "points" : 30,
                  "driver" : [ {"driverId" : 105,
                                "name"     : "George Russell",
                                "points"   : 12},
                               {"driverId" : 104,
                                "name"     : "Carlos Sainz Jr",
                                "points"   : 18} ]}')
      WHERE dv.DATA.name LIKE 'Ferrari%';

トランザクションをコミットします。

  DBMS_JSON_DUALITY.commit_transaction();
END;

関連項目:

  • プロシージャDBMS_JSON_DUALITY.begin_transactionの詳細は、Oracle Database PL/SQLパッケージおよびタイプ・リファレンスBEGIN_TRANSACTIONプロシージャ

  • プロシージャDBMS_JSON_DUALITY.commit_transactionの詳細は、Oracle Database PL/SQLパッケージおよびタイプ・リファレンスCOMMIT_TRANSACTIONプロシージャ

  • プロシージャDBMS_JSON_DUALITY.registerの詳細は、Oracle Database PL/SQLパッケージおよびタイプ・リファレンスREGISTERプロシージャ