12 JSONマージ・パッチによるJSONドキュメントの更新
Oracle SQLファンクションjson_mergepatch
を使用して、JSONドキュメントの特定の部分を更新できます。指定したJSONドキュメントに対する変更を指定するJSONマージ・パッチ・ドキュメントを渡します。JSONマージ・パッチはIETF標準です。
UPDATE
文でjson_mergepatch
を使用すると、JSON列のドキュメントを更新できます。例12-3に、これを示します。
SELECT
リストでjson_mergepatch
を使用すると、選択したドキュメントを変更できます。変更したドキュメントは、後で返したり、処理できます。例12-4に、これを示します。
JSONマージ・パッチは、主に構造にオブジェクトを使用し、明示的なnull
値を使用しないJSONドキュメントの更新に適しています。配列要素を追加、削除または変更することはできません(配列全体を明示的に置き換える場合を除く)。また、フィールドの値をnull
に設定することはできません。
JSONマージ・パッチは、UNIXのpatch
ユーティリティと同様に動作します。パッチを適用するソース・ドキュメントおよび変更を指定するパッチ・ドキュメントを指定すると、更新された(パッチが適用された)ソース・ドキュメントのコピーが返されます。パッチ・ドキュメントでは、ソースと結果のドキュメントの違いを指定します。UNIXのpatch
の場合、差異はUNIX diff
ユーティリティ出力の形式になります。JSONマージ・パッチの場合、ソースと宛先の両方がJSONドキュメントです。
JSONマージ・パッチは、ソースとパッチのコンテンツのマージとして考えることができます。2つのオブジェクト(ソースとパッチから1つずつ)をマージする場合、一方のオブジェクトにあるが他方には存在しないフィールドを持つメンバーは結果に保持されます。例外として、フィールド値がnull
であるパッチ・メンバーは、ソース・オブジェクトにそのようなフィールドがない場合には無視されます。
-
パッチ・フィールドの値が
NULL
の場合、フィールドはソース・ホースからドロップされ、結果に含まれません。 -
それ以外の場合、フィールドは結果に保持されますが、その値はソース・フィールド値とパッチ・フィールド値をマージした結果になります。つまり、この場合のマージ操作は、値自体がオブジェクトであるフィールドに対して再帰的に行われます。
より正確には、JSONマージ・パッチは次のように動作します。
-
パッチがJSONオブジェクトでない場合は、パッチでソースを置き換えます。
-
それ以外(パッチがオブジェクト)の場合は、次の手順を実行します。
-
ソースがオブジェクトでない場合は、空のオブジェクト(
{}
)であるかのように動作します。 -
パッチ・オブジェクトの(
p-field:p–value
)メンバーに対して繰り返されます。-
パッチ・メンバーの
p-value
がnull
の場合は、対応するメンバーをソースから削除します。 -
それ以外の場合は、再帰します。対応するソース・フィールドの値を、対応するソース・フィールドの値を、(次のパッチとして)
p-value
でその値を(次のソースとして)マージ・パッチ適用した結果で置き換えます。
-
-
パッチ・フィールド値null
に特別な意味がない場合(そのフィールドに対応するソース・メンバーを削除)、これをフィールド値として使用して対応するソース・フィールド値をnull
に設定できます。この特別な削除動作では、ソース・フィールド値をnull
に設定できません。
例:
-
パッチ・メンバー
"PONumber":99999
は、フィールドPONumber
でソース・メンバーをオーバーライドし、その値をパッチ指定の値99999
に置き換えます。json_mergepatch('{"User":"ABULL", "PONumber":1600}', '{"PONumber":99999}')
の結果は{"User":"ABULL", "PONumber":99999}
になります。 -
パッチ・メンバー
"tracking":123456
は、欠落したソース・メンバーをフィールドtracking
でオーバーライドし、そのパッチ・メンバーを結果に追加します。また、ソース・メンバー"PONumber":1600
は、フィールドPONumber
で欠落したパッチ・メンバーをオーバーライドします。これは結果に保持されます。json_mergepatch('{"PONumber":1600}', '{"tracking":123456}')
の結果は{"PONumber":1600, "tracking":123456}"
になります。 -
パッチ・メンバー
"Reference":null
は、フィールドReference
でソース・メンバーをオーバーライドし、結果から削除します。json_mergepatch('{"PONumber":1600, "Reference":"ABULL-20140421"}', '{"Reference":null}')
の結果は{"PONumber":1600}
になります。 -
パッチ値
[1,2,3]
は対応するソース値[4,5,6]
をオーバーライドして、置き換えます。json_mergepatch('{"PONumber":1600, "LineItems":[1, 2, 3]}', '{"LineItems":[4,5,6]}')
の結果は{"PONumber":1600, "LineItems":[4, 5, 6]}
になります。
ノート:
マージ・パッチ・プロシージャでは、特に、非オブジェクト・パッチに対する再帰的な動作がないことにより、配列の値を個別に追加、削除または置換できません。このような変更を加えるには、配列全体を置き換える必要があります。たとえば、ソース・ドキュメントにメンバーPhone:["999-555-1212", "415-555-1234"]
がある場合、2番目の電話番号を削除するには、コンテンツにメンバー"Phone":["999-555-1212"]
があるパッチを使用できます。
関連項目:
-
IETF RFC7396 (JSONマージ・パッチの定義)
-
Oracle Database SQL言語リファレンス(SQLファンクション
json_mergepatch
の詳細)
例12-1 JSONマージ・パッチ・ドキュメント
例2-1に示したドキュメントに適用される場合、このJSONマージ・パッチ・ドキュメントでは、次のことが実行されます。
-
メンバー
"Category" : "Platinum"
を追加します。 -
フィールド
ShippingInstructions
を持つメンバーを削除します。 -
フィールド
Special Instructions
の値を文字列"Contact User SBELL"
に置き換えます。 -
フィールド
LineItems
の値を空の配列[]
に置き換えます -
メンバー
"AllowPartialShipment" : null
をメンバー"Allow Partial Shipment" : false
に置き換えます(フィールド値がすでにfalse
であったため、実質的にはフィールドの名前が変更されます)。
{ "Category" : "Platinum",
"ShippingInstructions" : null,
"Special Instructions" : "Contact User SBELL",
"LineItems" : [],
"AllowPartialShipment" : null,
"Allow Partial Shipment" : false }
例12-2 マージ・パッチ適用されたJSONドキュメント
この例は、例2-1のドキュメントを例12-1のパッチでマージ・パッチ適用した結果のドキュメントを示しています。
{ "PONumber" : 1600,
"Reference" : "ABULL-20140421",
"Requestor" : "Alexis Bull",
"User" : "ABULL",
"CostCenter" : "A50",
"Special Instructions" : "Contact User SBELL",
"Allow Partial Shipment" : false,
"LineItems" : [],
"Category" : "Platinum" }
例12-3 JSONマージ・パッチを使用したJSON列の更新
この例では、j_purchaseorder.po_document
のすべてのドキュメントを更新して、フィールド"Special Instructions"
を削除します。
UPDATE j_purchaseorder SET po_document =
json_mergepatch(po_document, '{"Special Instructions":null}');
例12-4 選択したJSONドキュメントの即時更新
この例では、j_purchaseorder.po_document
内のすべてのドキュメントを選択し、フィールド"Special Instructions"
が削除されたドキュメントのフォーマット出力の更新済のコピーを返します。
SELECT json_mergepatch(po_document, '{"Special Instructions":null}'
RETURNING CLOB PRETTY)
FROM j_purchaseorder;