2025年3月12日水曜日

APEX 24.2.3で二面性ビューを使用する

Oracle APEX 24.2.3のパッチセットにて、データ・ソース二面性ビューが作成できない不具合が修正されました。(BUG#37538056 - CREATE DUALITY VIEW SOURCE THROWS ORA-6503 ON DB 23.6)

Oracle APEX 24.2.3でデータ・ソースとして二面性ビューを作成し、使用方法を確認してみます。二面性ビューとして、以前の記事で作成したDEPTEMP_SQL_DVを使用します。

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なので、主キーは正しく検出されています。

この条件で二面性ビューを作成します。


APEXのデータ・ソース二面性ビューDEPTEMP_SQL_DVとして作成されました。


作成された二面性ビューを開き、検出されたデータ・プロファイルを確認します。


以下のコマンドを実行すると、二面性ビューのJSONスキーマを印刷できます。
begin
    dbms_output.put_line(json_serialize(dbms_json_schema.describe('DEPTEMP_SQL_DV') returning clob pretty));
end;
二面性ビューDEPTEMP_SQL_DVのJSONスキーマとして、以下が印刷されます。

{
"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を選択します。

へ進みます。


主キー列1ID (Number)主キー列2EMPNO (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に含まれる従業員の情報に限定されます。従業員が所属している部門の情報は設定も更新もできません。
そのため、ページ作成ウィザードによって作成されるフォームでは、従業員の新規登録と、既存の従業員の所属部署の更新はできません。フォームをカスタマイズする必要があります。

今回の記事は以上になります。