2023年6月2日金曜日

JSONが保存された列を対象としたレポートとフォームを作る

Oracle APEXは表の定義情報を参照することにより、レポートの列やフォームのアイテムを生成します。列にJSONが保存されている場合は、その内容からレポートの列やフォームのアイテムを生成するといったことはできません。

なんとなくJSON_DATAGUIDEDBMS_JSON.CREATE_VIEWを使うことで、JSON列を対象としたレポートとフォームの作成が容易になるように思ったので実装してみました。

最初にデータを準備します。

サンプル・データセットのEMP/DEPTに含まれる表EMPを、JSONとして保存する表EMPJを作成します。

create table empj (
    "_ID" number primary key,
    document blob check (document is json)
);

表EMPの主キーは列EMPNOですが、この表EMPJに列EMPNOを作成すると、列DOCUMENTのJSONのデータにもEMPNOが含まれていることから、列名が競合します。そのため、競合しない名前"_ID"という列を作成し、主キーとしています。


表EMPよりJSONデータを生成し、表EMPJに入れ替えます。

insert into empj select empno, json_object(*) from emp;


列DOCUMENTのJSONデータガイドを取得し、それを元にビューEMP_JVを作成します。


作成したビューEMP_JVより、表EMPJの内容を確認します。

select * from emp_jv;

JSONなのでHIREDATEがISO8601形式になっていますが、JSON形式で保存されているデータが表形式で確認できています。


 作成されたビューEMP_JVの列の型を確認してみます。

select column_name, data_type, data_length from all_tab_cols where table_name = 'EMP_JV';

COLUMN_NAMEDATA_TYPEDATA_LENGTH
JOBVARCHAR216
MGRVARCHAR24
SALNUMBER22
COMMVARCHAR22
EMPNONUMBER22
ENAMEVARCHAR28
DEPTNONUMBER22
HIREDATEVARCHAR232
_IDNUMBER22

この定義は、以下のJSONデータガイドが元になっています。

select json_dataguide(document,dbms_json.format_hierarchical) from empj;

JSONデータガイドの出力です。
{
  "type": "object",
  "o:length": 1,
  "properties": {
    "JOB": {
      "type": "string",
      "o:length": 16,
      "o:preferred_column_name": "JOB"
    },
    "MGR": {
      "type": "string",
      "o:length": 4,
      "o:preferred_column_name": "MGR"
    },
    "SAL": {
      "type": "number",
      "o:length": 4,
      "o:preferred_column_name": "SAL"
    },
    "COMM": {
      "type": "string",
      "o:length": 2,
      "o:preferred_column_name": "COMM"
    },
    "EMPNO": {
      "type": "number",
      "o:length": 4,
      "o:preferred_column_name": "EMPNO"
    },
    "ENAME": {
      "type": "string",
      "o:length": 8,
      "o:preferred_column_name": "ENAME"
    },
    "DEPTNO": {
      "type": "number",
      "o:length": 2,
      "o:preferred_column_name": "DEPTNO"
    },
    "HIREDATE": {
      "type": "string",
      "o:length": 32,
      "o:preferred_column_name": "HIREDATE"
    }
  }
}
ビューEMP_JVができたので、これを元にAPEXのアプリケーションを作成します。

アプリケーション作成ウィザードを起動し、空のアプリケーションを作成します。

名前JSONフォームとします。


アプリケーションが作成されたら、ページ作成ウィザードを起動し、ビューEMP_JVソースとした対話モード・レポートフォームのページを作成します。


対話モード・レポートを選択します。


 ページ定義ページ番号名前従業員一覧とします。フォーム・ページを含めるオンにします。フォーム・ページ番号フォーム・ページ名従業員編集とします。フォーム・ページ・モードドロワーとします。

データ・ソース表/ビューの名前としてEMP_JVを指定します。ビューEMP_JVは更新できませんが、これはAPEXのプロセスにコードを記述して対応します。

へ進みます。


主キー列1として_ID(Number)を選択します。

ページの作成をクリックします。


ページが作成されたら、対話モード・レポートを表示します。

ビューEMP_JVを読んでいるだけなので、対話モード・レポートは問題なさそうです。


編集アイコンをクリックし、フォームを開きます。

ビューEMP_JVの列からページ・アイテムが作成されています。また、ページ・アイテムの値の設定もできています。


ビューは更新できないため、プロセス・フォーム従業員編集設定ターゲット・タイプPL/SQL Codeに変更し、以下のコードを記述します。


また、行のロックはビューEMP_JVではなく、表EMPJに対して実施します。行のロックPL/SQL Codeに変更し、以下のコードを記述します。(列DOCUMENTの定義にformat osonを付加している場合は、行のロックNoにします。)




以上でアプリケーションは完成です。

簡単な例で確認しただけですが、レポートやフォームを素早く作ることはできているので、アプローチとしては悪くなさそうです。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/json-form.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。