11 Oracle SQLファンクションJSON_TRANSFORM
Oracle SQLファンクションjson_transform
はJSON文書を変更します。実行する変更操作、および変更する場所を示すSQL/JSONパス式を指定します。各操作は、指定した順序で入力データに適用され、それ以前の操作がすべて適用された結果に作用します。
ファンクションjson_transform
はアトミック型です。操作を試行してエラーが発生した場合、その操作は一切有効になりません。json_transform
は、完全に成功してデータが要求されたとおりに変更されるか、データは変更されません。json_transform
は、引数での指定どおりに変更された元のデータを返します。
SQL UPDATE
文でjson_transform
を使用すると、JSON列のドキュメントを更新できます。例11-1に、これを示します。
SELECT
のリストでそれを使用すると、選択した文書を変更できます。変更したドキュメントは、後で返したり、処理できます。例11-2に、これを示します。
ファンクションjson_transform
は、JSONデータをサポートするSQLデータ型を入力として受け取り、出力として返すことができます。
デフォルトの戻り(出力)データ型は、入力データ型と同じです。脚注1(入力が任意のサイズのVARCHAR2
の場合、デフォルトはVARCHAR2(4000))
です。
制限された適用性を持つOracle SQLファンクションjson_mergepatch
(主に構造にオブジェクトを使用し、明示的なnull
値を使用しないJSON文書を更新する場合に適しています)とは異なり、json_transform
は一般的な変更関数です。
json_transform
の1回の呼出しで複数の操作を実行するように指定すると、指定した順序で操作が順番に実行されます。このため、各操作は前のすべての操作が適用された結果に対して作用します。
指定する変更操作の順序に従って、オプションのRETURNING
句およびPASSING
句を含めることができます。RETURNING
句は、SQL/JSONファンクションjson_query
の場合と同じです。PASSING
句は、SQL/JSON条件json_exists
の場合と同じです。これらは、それぞれ戻りデータ型とSQLバインド変数を指定します。
使用可能な変更操作は次のとおりです。
-
REMOVE
— 指定されたパス式で対象となる入力データを削除します。すべてのデータを削除しようとすると、エラーが発生します。つまり、REMOVE '$'
は使用できません。デフォルトでは、対象となるデータが存在しない場合、エラーは発生しません(IGNORE ON MISSING
)。 -
KEEP
— 少なくとも1つの指定されたパス式で対象とされていない入力データのすべての部分を削除します。最上位のオブジェクトまたは配列は削除されません。それは空にされて、空のオブジェクト({}
)または配列([]
)になります。 -
RENAME
— 指定されたパス式で対象となるフィールドの名前を、等号(=
)に続くSQL式の値に変更します。デフォルトでは、対象となるフィールドが存在しない場合、エラーは発生しません(IGNORE ON MISSING
)。 -
SET
— 指定されたパス式で対象となるデータに、指定されたSQL式の値を設定します。デフォルトの動作は、SQLのUPSERT
と似ています。つまり、既存の対象となるデータが新しい値に置き換えられます。パス式がまったく一致しない場合は、対象となる場所に新しい値が挿入されます。(配列の末尾を超える配列要素の挿入については、演算子
INSERT
を参照してください。) -
REPLACE
— 指定されたパス式で対象となるデータを、指定されたSQL式の値に置き換えます。デフォルトでは、対象となるデータが存在しない場合、エラーは発生しません(IGNORE ON MISSING
)。(
REPLACE
には、IGNORE ON MISSING
句を指定したSET
と同じ効果があります。) -
INSERT
— 指定されたパス式で対象となる場所に、指定されたSQL式の値を挿入します。この場所は、オブジェクトのフィールドまたは配列の位置のいずれかである必要があります(そうでない場合は、エラーが発生します)。デフォルトでは、対象となるオブジェクトのフィールドがすでに存在する場合、エラーが発生します。(オブジェクトのフィールドの
INSERT
は、CREATE ON MISSING
句(SET
のデフォルト)を指定したSET
と同じ効果があります。ただし、ON EXISTING
のデフォルトの動作は、REPLACE
ではなくERROR
です。)配列の現在の末尾より後の配列の位置を指定できます。その場合、配列は指定された位置への値の挿入に対応するように長さが調整され、間にある位置にはJSONの
null
値が設定されます。たとえば、入力のJSONデータが
{"a":["b"]}
の場合、INSERT '$.a[3]'=42
は変更されたデータとして{"a":["b", null, null 42]}
を返します。配列位置1および2の要素は、null
です。 -
APPEND
— 指定されたSQL式の値を対象となる配列の末尾に追加します。デフォルトでは、パス式が配列を対象としない場合は、エラーが発生します。(
APPEND
は、last+1
の配列位置へのINSERT
の効果があります。)
各種の操作のキーワードの直後には、その操作で対象となるデータのパス式を指定します。KEEP
操作は、キーワードの後に1つ以上のパス式が続く例外です。このパス式は、維持するデータを指定します。これらのパス式の少なくとも1つの対象となっていないすべてのデータは削除されます。
KEEP
およびREMOVE
を除くすべての操作では、パス式の後に等号(=
)があり、次にSQLの結果式が続きます。これが評価され、結果値を使用して対象となるデータが変更されます。脚注1
RENAME
操作では、結果式はSQL文字列に評価される必要があります。そうでない場合は、エラーが発生します。
RENAME
を除くすべての操作で、結果式は、JSON値としてレンダリングできるSQL値に評価される必要があります。そうでない場合は、不適切なSQLデータ型が原因でエラーが発生します。(これは、SQL/JSON生成関数json_object
に指定する名前と値のペアの値の部分の要件と同じです。)
式の直後にキーワードFORMAT JSON
を続けることで、結果式の評価をJSONデータに変換できます。これは、SQL文字列'true'
または'false'
を、対応するJSON言語値true
またはfalse
に変換する場合に特に便利です。例11-7に、これを示します。
操作の指定の最後の部分は、オプションの一連のハンドラです。各操作に対して異なるハンドラが許可され、ハンドラのデフォルトが異なります。(その操作を許可しないハンドラを操作に指定した場合は、エラーが発生します。)
次の3種類のハンドラがあります。
-
ON EXISTING
— パス式がデータと一致した場合に行う動作を指定します。つまり、少なくとも1つの値を対象とします。-
ERROR ON EXISTING
—エラーを発生させます。 -
IGNORE ON EXISTING
—データを変更しません(変更なし)。 -
REPLACE ON EXISTING
—対象となる場所のデータをSQLの結果式の値に置き換えます。 -
REMOVE ON EXISTING
—対象となるデータを削除します。
-
-
ON MISSING
— パス式がデータと一致しない場合に行う動作を指定します。つまり、少なくとも1つの値を対象としません。-
ERROR ON MISSING
—エラーを発生させます。 -
IGNORE ON MISSING
—データを変更しません(変更なし)。 -
CREATE ON MISSING
—対象となる位置にデータを追加します。
パス式配列ステップでは、
ON MISSING
ハンドラは、対象となる配列自体がデータから欠落していることを意味しません。それはかわりにON EMPTY
ハンドラによって対応されます。ON MISSING
ハンドラは、配列ステップによって指定された1つ以上の位置がデータと一致しない場合に対応します。たとえば、配列ステップ[2]
はデータ配列["a", "b"]
と一致しません。この配列には位置2に要素がないためです。 -
-
ON NULL
— SQLの結果式の値がNULL
の場合に行う動作を指定します。-
NULL ON NULL
—対象となる場所にJSONのnull
値を使用します。 -
ERROR ON NULL
—エラーを発生させます。 -
IGNORE ON NULL
—データを変更しません(変更なし)。 -
REMOVE ON NULL
—対象となるデータを削除します。
ON NULL
を許可するすべてのハンドラのデフォルトの動作は、NULL ON NULL
です。 -
様々な操作に許可されるハンドラは、次のとおりです。
-
REMOVE
:IGNORE ON MISSING
(デフォルト)、ERROR ON MISSING
-
KEEP
: ハンドラなし -
RENAME
:IGNORE ON MISSING
(デフォルト)、ERROR ON MISSING
-
SET
:-
REPLACE ON EXISTING
(デフォルト)、ERROR ON EXISTING
、IGNORE ON EXISTING
-
CREATE ON MISSING
(デフォルト)、ERROR ON MISSING
、IGNORE ON MISSING
-
NULL ON NULL
(デフォルト)、ERROR ON NULL
、IGNORE ON NULL
、REMOVE ON NULL
-
-
REPLACE
:-
IGNORE ON MISSING
(デフォルト)、ERROR ON MISSING
、CREATE ON MISSING
-
NULL ON NULL
(デフォルト)、ERROR ON NULL
、IGNORE ON NULL
、REMOVE ON NULL
-
-
INSERT
:-
ERROR ON EXISTING
(デフォルト)、IGNORE ON EXISTING
、REPLACE ON EXISTING
-
NULL ON NULL
(デフォルト)、ERROR ON NULL
、IGNORE ON NULL
、REMOVE ON NULL
-
-
APPEND
:-
ERROR ON MISSING
(デフォルト)、IGNORE ON MISSING
、CREATE ON MISSING
。作成は、対象となる場所に単一の配列を挿入することを意味します。単一の配列要素は、SQLの結果式の値です。 -
NULL ON NULL
(デフォルト)、ERROR ON NULL
、IGNORE ON NULL
-
例11-1 JSON_TRANSFORMを使用したJSON列の更新
この例では、lastUpdated
フィールドの値に現在のタイムスタンプを設定して、j_purchaseorder.po_document
内のすべての文書を更新します。
フィールドがすでに存在する場合はその値が置き換えられ、存在しない場合はフィールドとその値が追加されます。(つまり、デフォルトのハンドラ(REPLACE ON EXISTING
およびCREATE ON MISSING
)が使用されます。)
UPDATE j_purchaseorder SET po_document =
json_transform(po_document, SET '$.lastUpdated' = SYSTIMESTAMP);
例11-2 JSON_TRANSFORMによるJSONデータの即時の変更
この例では、j_purchaseorder.po_document
内のすべてのドキュメントを選択し、フィールド"Special Instructions"
が削除されたドキュメントのフォーマット出力の更新済のコピーを返します。
フィールドが存在しない場合は、何も行われません(エラーは発生しません)。IGNORE ON MISSING
がデフォルトの動作です。
戻りデータ型はCLOB
です。
SELECT json_transform(po_document, REMOVE '$."Special Instructions"'
RETURNING CLOB PRETTY)
FROM j_purchaseorder;
例11-3 JSON_TRANSFORMを使用したフィールドの追加
次の2つのjson_tranform
の使用方法は同等です。これらはどちらも、Comments
フィールドとその値"Helpful"
を追加します。フィールドがすでに存在する場合、エラーが発生します。フィールド値の入力は、リテラルのSQL文字列'Helpful'
です。SET
のデフォルトの動作は、CREATE ON MISSING
です。
json_transform(po_document, INSERT '$.Comments' = 'Helpful')
json_transform(po_document, SET '$.Comments' = 'Helpful'
ERROR ON EXISTING)
例11-4 JSON_TRANSFORMを使用したフィールドの削除
この例では、Special Instructions
フィールドを削除します。フィールドが存在しない場合は、何も行われません(エラーは発生しません)。IGNORE ON MISSING
がデフォルトの動作です。
json_transform(po_document, REMOVE '$.Special Instructions')
例11-5 JSON_TRANSFORMを使用したフィールド値の作成または置換
この例では、Address
フィールドの値にJSONオブジェクト{"street":"8 Timbly Lane", "city":"Penobsky", "state":"Utah"}
が設定されます。フィールドが存在しない場合はフィールドが作成されます。フィールドの既存の値が置き換えられます。フィールド値の入力はリテラルのSQL文字列です。入力値にFORMAT JSON
が指定されているため、更新されたフィールド値はJSONオブジェクトです。
json_transform(po_document,
SET '$.Address' =
'{"street":"8 Timbly Rd.",
"city":"Penobsky",
"state":"UT"}'
FORMAT JSON)
FORMAT JSON
を使用しない場合、Address
フィールドの値はSQL入力文字列に対応するJSON 文字列になります。入力の各二重引用符("
)文字は、JSON文字列ではエスケープされます。
"{\"street\":\"8 Timbly Rd.\","city\":\"Penobsky\",\"state\":\"UT\"}"
例11-6 JSON_TRANSFORMを使用した既存のフィールド値の置換
この例では、Address
フィールドの値にJSONオブジェクト{"street":"8 Timbly Lane", "city":"Penobsky", "state":"Utah"}
が設定されます。フィールドの既存の値が置き換えられます。フィールドが存在しない場合は何も行われません。この例と例11-5の違いは、IGNORE ON MISSING
ハンドラが存在することのみです。
json_transform(po_document,
SET '$.Address' =
'{"street":"8 Timbly Rd.",
"city":"Penobsky",
"state":"UT"}'
FORMAT JSON
IGNORE ON MISSING)
例11-7 FORMAT JSONを使用したJSONのブール値の設定
この例では、フィールドAllowPartialShipment
の値をJSON言語のブール値true
に設定します。キーワードFORMAT JSON
を指定しないと、かわりにフィールドにJSON言語の文字列"true"
が設定されます。
json_transform(po_document,
SET '$.AllowPartialShipment' = 'true' FORMAT JSON)
例11-8 JSON_TRANSFORMを使用した配列要素の設定
この例では、配列Phone
の先頭の要素にJSON文字列"909-555-1212"
が設定されます。
json_transform(po_document,
SET '$.ShippingInstructions.Phone[0]' = '909-555-1212')
操作の前の配列Phone
の値が次の値の場合:
[{"type":"Office","number":"909-555-7307"},
{"type":"Mobile","number":415-555-1234"}]
変更後の値は次のようになります。
["909-555-1212",
{"type":"Mobile","number":415-555-1234"}]
例11-9 JSON_TRANSFORMを使用した配列の先頭への要素の追加
この例では、要素"909-555-1212"
が配列Phone
の先頭に追加されます。位置0に挿入すると、既存のすべての要素が右にシフトされます。要素Nは要素N+1になります。
json_transform(po_document,
INSERT '$.ShippingInstructions.Phone[0]' =
'909-555-1212')
例11-10 JSON_TRANSFORMを使用した配列の末尾への要素の追加
次の2つのjson_tranform
の使用方法は同等です。これらはどちらも、要素"909-555-1212"
を配列Phone
の末尾に追加します。
json_transform(po_document,
APPEND '$.ShippingInstructions.Phone' =
'909-555-1212')
json_transform(po_document,
INSERT '$.ShippingInstructions.Phone[last+1]' =
'909-555-1212')
関連項目:
Oracle SQLファンクションjson_transform
の詳細は、『Oracle Database SQL言語リファレンス』
親トピック: JSONデータの挿入、更新およびロード
脚注の凡例
脚注1: ファンクションjson_transform
のSQL戻り型と、KEEP
およびREMOVE
以外の変更操作で等号(=
)に続くSQL結果式の型を混同しないでください。