Oracle APEX 24.2.3でデータ・ソースとして二面性ビューを作成し、使用方法を確認してみます。二面性ビューとして、以前の記事で作成したDEPTEMP_SQL_DVを使用します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
create or replace json relational duality view deptemp_sql_dv as | |
select json{ '_id': d.deptno, | |
'dname': d.dname, | |
'loc': d.loc, | |
'employees': | |
[ select json{ 'empno': e.empno, | |
'ename': e.ename, | |
'job': e.job, | |
'hiredate': e.hiredate, | |
'compensation': { | |
'sal': e.sal, | |
'comm': e.comm | |
} | |
} | |
from emp e | |
with insert update delete | |
where e.deptno = d.deptno | |
] | |
} | |
from dept d | |
with insert update delete nocheck | |
/ |
最初に空のアプリケーションを作成します。名前は二面性ビューとします。
アプリケーションが作成されます。共有コンポーネントを開きます。
二面性ビューを開きます。
作成済みの二面性ビューが一覧されます。作成をクリックします。
あくまで、APEXのデータ・ソースとして扱う二面性ビューの作成であり、データベース・オブジェクトとしての二面性ビュー(JSON Relational Duality View)は、あらかじめ作成されている必要があります。今回の例では、データベース・オブジェクトのDEPTEMP_SQL_DVは、すでに作成されています。
作成する二面性ビューの名前は、データベース・オブジェクトと同じDEPTEMP_SQL_DVとします。二面性ビューにデータベース・オブジェクトであるDEPTEMP_SQL_DVを選択します。
次へ進みます。
不具合は修正されています。そのためエラーは発生せず、次のページに進みます。
検出されたデータ・プロファイルが一覧されます。
列ID、セレクタ_idおよび列EMPNO、セレクタempnoの双方が主キーとして認識されています。列IDはビューの元表DEPTの主キーDEPTNOであり、EMPNOは元表EMPの主キー列EMPNOなので、主キーは正しく検出されています。
この条件で二面性ビューを作成します。
以下のコマンドを実行すると、二面性ビューのJSONスキーマを印刷できます。
begin
dbms_output.put_line(json_serialize(dbms_json_schema.describe('DEPTEMP_SQL_DV') returning clob pretty));
end;
二面性ビューDEPTEMP_SQL_DVのJSONスキーマとして、以下が印刷されます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"title" : "DEPTEMP_SQL_DV", | |
"dbObject" : "WKSP_APEXDEV.DEPTEMP_SQL_DV", | |
"dbObjectType" : "dualityView", | |
"dbObjectProperties" : | |
[ | |
"insert", | |
"update", | |
"delete", | |
"check" | |
], | |
"type" : "object", | |
"properties" : | |
{ | |
"_metadata" : | |
{ | |
"etag" : | |
{ | |
"type" : "string", | |
"extendedType" : "string", | |
"maxLength" : 200 | |
}, | |
"asof" : | |
{ | |
"type" : "string", | |
"extendedType" : "string", | |
"maxLength" : 20 | |
} | |
}, | |
"loc" : | |
{ | |
"oneOf" : | |
[ | |
{ | |
"type" : "null", | |
"extendedType" : "null" | |
}, | |
{ | |
"type" : "string", | |
"extendedType" : "string", | |
"maxLength" : 13 | |
} | |
], | |
"dbFieldProperties" : | |
[ | |
"update" | |
] | |
}, | |
"dname" : | |
{ | |
"oneOf" : | |
[ | |
{ | |
"type" : "null", | |
"extendedType" : "null" | |
}, | |
{ | |
"type" : "string", | |
"extendedType" : "string", | |
"maxLength" : 14 | |
} | |
], | |
"dbFieldProperties" : | |
[ | |
"update" | |
] | |
}, | |
"_id" : | |
{ | |
"type" : "number", | |
"extendedType" : "number", | |
"sqlPrecision" : 2, | |
"sqlScale" : 0, | |
"dbFieldProperties" : | |
[ | |
"check" | |
] | |
}, | |
"employees" : | |
{ | |
"type" : "array", | |
"extendedType" : "array", | |
"items" : | |
{ | |
"type" : "object", | |
"properties" : | |
{ | |
"job" : | |
{ | |
"oneOf" : | |
[ | |
{ | |
"type" : "null", | |
"extendedType" : "null" | |
}, | |
{ | |
"type" : "string", | |
"extendedType" : "string", | |
"maxLength" : 9 | |
} | |
], | |
"dbFieldProperties" : | |
[ | |
"update", | |
"check" | |
] | |
}, | |
"empno" : | |
{ | |
"type" : "number", | |
"extendedType" : "number", | |
"sqlPrecision" : 4, | |
"sqlScale" : 0, | |
"dbFieldProperties" : | |
[ | |
"check" | |
] | |
}, | |
"ename" : | |
{ | |
"oneOf" : | |
[ | |
{ | |
"type" : "null", | |
"extendedType" : "null" | |
}, | |
{ | |
"type" : "string", | |
"extendedType" : "string", | |
"maxLength" : 10 | |
} | |
], | |
"dbFieldProperties" : | |
[ | |
"update", | |
"check" | |
] | |
}, | |
"hiredate" : | |
{ | |
"oneOf" : | |
[ | |
{ | |
"type" : "null", | |
"extendedType" : "null" | |
}, | |
{ | |
"type" : "number", | |
"extendedType" : "date" | |
} | |
], | |
"dbFieldProperties" : | |
[ | |
"update", | |
"check" | |
] | |
}, | |
"compensation" : | |
{ | |
"type" : "object", | |
"properties" : | |
{ | |
"comm" : | |
{ | |
"oneOf" : | |
[ | |
{ | |
"type" : "null", | |
"extendedType" : "null" | |
}, | |
{ | |
"type" : "number", | |
"extendedType" : "number", | |
"sqlPrecision" : 7, | |
"sqlScale" : 2 | |
} | |
], | |
"dbFieldProperties" : | |
[ | |
"update", | |
"check" | |
] | |
}, | |
"sal" : | |
{ | |
"oneOf" : | |
[ | |
{ | |
"type" : "null", | |
"extendedType" : "null" | |
}, | |
{ | |
"type" : "number", | |
"extendedType" : "number", | |
"sqlPrecision" : 7, | |
"sqlScale" : 2 | |
} | |
], | |
"dbFieldProperties" : | |
[ | |
"update", | |
"check" | |
] | |
} | |
} | |
} | |
}, | |
"dbPrimaryKey" : | |
[ | |
"empno" | |
], | |
"required" : | |
[ | |
"empno" | |
], | |
"additionalProperties" : false | |
} | |
} | |
}, | |
"dbPrimaryKey" : | |
[ | |
"_id" | |
], | |
"required" : | |
[ | |
"_id" | |
], | |
"additionalProperties" : false | |
} |
検出されたデータ・プロファイルを確認すると、概ねJSONスキーマの定義を反映しています。
この中で、列APEX_METADATA_ETAGおよびAPEX_METADATA_ASOFは二面性ビューの楽観的ロックの実装に関わる列です。これらの列の共通がいいえになっています。共通がいいえの場合、ページ作成ウィザードはレポートやフォームのページを作成する際に、これらを生成対象から除外します。結果として、Oracle APEXが二面性ビューを扱う際に、楽観的ロックはAPEXの実装を適用し、二面性ビューのmetadata.etagは使用しません。
データ・プロファイルの列にはEMPLOYEES_POSとして、JSONスキーマの定義には含まれない(セレクタがない)列が含まれます。これは、"EMPLOYEES_POS" for ordinalityとして値が生成されている、配列EMPLOYEESの中の要素の位置を示す数値です。共通ははいになっています。(for ordinalityについてはJSON_TABLEのリファレンスを参照のこと)。
実際に、このデータ・ソースを使用したフォーム付き対話モード・レポートのページを作成します。
ページの作成をクリックします。
対話モード・レポートを選択します。
対話モード・レポートのページの名前をEmployees、フォーム・ページを含めるをオンにし、フォーム・ページ名はEmployee Detailとします。
データ・ソースに二面性ビューを選び、二面性ビューとして先ほど作成したDEPTEMP_SQL_DVを指定します。ネストした行に1. EMPLOYEESを選択します。
次へ進みます。
主キー列1にID (Number)、主キー列2にEMPNO (Number)を選択します。
ページの作成をクリックします。
以上で二面性ビューDEPTEMP_SQL_DVをデータ・ソースとした、対話モード・レポートとフォームのページが作成されます。
作成された対話モード・レポートを確認します。
データ・ソースの二面性ビューとしてDEPTEMP_SQL_DV、データ・プロファイルのネストした行として1. EMPLOYEESが選択されています。
データ・プロファイルの共通がいいえであるため、APEX_METADATA_ETAGおよびAPEX_METADATA_ASOFは列として作成されていません。EMPLOYEES_POSは共通がはいであるため、列として生成されています。二面性ビューDEPTEMP_SQL_DVのemployees配列は、元はリレーショナル表のEMPであり、リレーショナル表の要素の出現順序に意味はありません。
作成された対話モード・レポートの表示です。列Employees Posの表示は無くてもよいように思います。
フォームについても、データ・ソースの二面性ビューとしてDEPTEMP_SQL_DV、データ・プロファイルのネストした行として1. EMPLOYEESが選択されています。
ページ・アイテムにP3_EMPLOYEES_POSが含まれていますが、タイプが表示のみで、ソースの問い合せのみがオンであるため、(設定のページの送信時に送信はオンですが)本当に表示だけで、チェックサムの計算や更新の対象にはなっていません。
フォームは以下のように表示されます。二面性ビューのJSONスキーマを元にAPEXのデータ・ソースの二面性ビューのデータ・プロファイルが作成されているため、それを元に生成されたフォームのページ・アイテムも適切なタイプが設定されています。
ここでもEmployees Posが表示されますが、これは無くてもよいでしょう。
EMPLOYEES_POSのデータ・プロファイルの共通をいいえにすると、レポートの列やフォームのページ・アイテムとして生成されなくなります。
APEXのページ作成ウィザードは以下のルールでフォームを作成します。
- 主キーは自動採番のサロゲート・キーが想定されており、ページ・アイテムのタイプは非表示になります。上記では列EMPNOが非表示のページ・アイテムです。
- ネストする列として1. EMPLOYEESを選択しているため、更新対象は配列employeesに含まれる従業員の情報に限定されます。従業員が所属している部門の情報は設定も更新もできません。
そのため、ページ作成ウィザードによって作成されるフォームでは、従業員の新規登録と、既存の従業員の所属部署の更新はできません。フォームをカスタマイズする必要があります。
今回の記事は以上になります。
完