Oracle APEXのPL/SQL APIとして提供されているファンクションAPEX_REGION.OPEN_QUERY_CONTEXTの引数にp_outer_sqlがあります。これを使用して、以下の機能を実装します。
- サンプル・データセットに含まれる表EMPを準備する。
- 表EMPのファセット検索ページを作成する。
- ファセットを使って表EMPの検索(従業員の絞り込み)を行う。
- 検索結果の列SALおよびCOMMの合計、平均、最小値、最大値、件数を別のレポートに表示する。
- 合計値などは、ファセットを変更する度に更新する。
サンプル・データセットのEMP/DEPTのインストール
すでにインストール済みの場合は、ボタンが更新になっています。その場合は、表EMPおよびDEPTが作成済みなので、追加の作業は不要です。
表EMPやDEPTを変更している場合(列をドロップしている等)は、更新を開いてインストール済みのデータセットを削除し、再度インストールし直す必要があります。データのみ変更している場合(例えば表EMPの行をすべて削除している等)は、リフレッシュするといった準備が必要になります。
アプリケーションの作成
アプリケーションを作成します。
アプリケーション・ビルダーを開き作成を実行して、アプリケーション作成ウィザードを起動します。
名前はファセット検索サマリーとします。ホーム・ページの編集をクリックして、このページを削除します。
削除をクリックします。
ページの追加をクリックし、ファセット検索のページを追加します。
ファセット検索を選択します。
ページ名は従業員検索とします。表示形式はレポートとし、ソースとなる表にEMPを選択します。編集は行わないため、フォームを含めるはチェックしません。
ページの追加をクリックします。
以上でアプリケーションの作成を実行します。
アプリケーションが作成されます。
今回の機能はページ1の従業員検索のページに実装します。
集計をレポートするパイプライン表関数の作成
ファセット検索の結果に集計関数を適用するパイプライン表関数emp_summaryを作成します。
以下のコードを実行します。
drop type "T_EMP_SUMMARY_TAB"; | |
/ | |
/* | |
* 表EMPのサマリーとなる行のタイプ | |
*/ | |
CREATE OR REPLACE EDITIONABLE TYPE "T_EMP_SUMMARY_ROW" as object( | |
sal_sum number | |
, sal_avg number | |
, sal_min number | |
, sal_max number | |
, sal_cnt number | |
, comm_sum number | |
, comm_avg number | |
, comm_min number | |
, comm_max number | |
, comm_cnt number | |
); | |
/ | |
/* | |
* パイプライン表関数の返り値となるタイプ | |
*/ | |
CREATE OR REPLACE EDITIONABLE TYPE "T_EMP_SUMMARY_TAB" as table of t_emp_summary_row; | |
/ | |
/* | |
* 表EMPのファセット検索の結果がレポートされているリージョンを引数として、 | |
* そのSUM、AVG、MIN、MAX、COUNTを返すパイプライン表関数の実装。 | |
*/ | |
create or replace function emp_summary( | |
p_app_id in number | |
, p_page_id in number | |
, p_region in varchar2 | |
) return t_emp_summary_tab pipelined | |
is | |
l_region_id number; | |
l_context apex_exec.t_context; | |
/* | |
* p_outer_sqlの定義。 | |
* ファセット検索の結果が#APEX$SOURCE_DATA#であり、 | |
* その結果に集計関数を適用している。 | |
*/ | |
C_OUTER_SQL constant varchar2(4000) := q'~ | |
select | |
sum(sal) sal_sum | |
, avg(sal) sal_avg | |
, min(sal) sal_min | |
, max(sal) sal_max | |
, count(sal) sal_cnt | |
, sum(comm) comm_sum | |
, avg(comm) comm_avg | |
, min(comm) comm_min | |
, max(comm) comm_max | |
, count(comm) comm_cnt | |
from #APEX$SOURCE_DATA# | |
~'; | |
l_idx_sal_sum pls_integer; | |
l_idx_sal_avg pls_integer; | |
l_idx_sal_min pls_integer; | |
l_idx_sal_max pls_integer; | |
l_idx_sal_cnt pls_integer; | |
l_idx_comm_sum pls_integer; | |
l_idx_comm_avg pls_integer; | |
l_idx_comm_min pls_integer; | |
l_idx_comm_max pls_integer; | |
l_idx_comm_cnt pls_integer; | |
begin | |
-- リージョンの静的IDからリージョンIDを取得する。 | |
select region_id into l_region_id from apex_application_page_regions | |
where application_id = p_app_id and page_id = p_page_id | |
and static_id = p_region; | |
-- ファセット検索の結果の合計値などの検索を実行する。 | |
l_context := apex_region.open_query_context( | |
p_page_id => p_page_id | |
, p_region_id => l_region_id | |
, p_outer_sql => C_OUTER_SQL | |
); | |
-- 列の位置を取得する。 | |
l_idx_sal_sum := apex_exec.get_column_position(l_context, 'SAL_SUM'); | |
l_idx_sal_avg := apex_exec.get_column_position(l_context, 'SAL_AVG'); | |
l_idx_sal_min := apex_exec.get_column_position(l_context, 'SAL_MIN'); | |
l_idx_sal_max := apex_exec.get_column_position(l_context, 'SAL_MAX'); | |
l_idx_sal_cnt := apex_exec.get_column_position(l_context, 'SAL_CNT'); | |
l_idx_comm_sum := apex_exec.get_column_position(l_context, 'COMM_SUM'); | |
l_idx_comm_avg := apex_exec.get_column_position(l_context, 'COMM_AVG'); | |
l_idx_comm_min := apex_exec.get_column_position(l_context, 'COMM_MIN'); | |
l_idx_comm_max := apex_exec.get_column_position(l_context, 'COMM_MAX'); | |
l_idx_comm_cnt := apex_exec.get_column_position(l_context, 'COMM_CNT'); | |
-- 検索結果を取り出す。whileループを使っているが、検索結果は1行のみ。 | |
while apex_exec.next_row(l_context) | |
loop | |
pipe row( | |
t_emp_summary_row( | |
apex_exec.get_number(l_context, l_idx_sal_sum) | |
, apex_exec.get_number(l_context, l_idx_sal_avg) | |
, apex_exec.get_number(l_context, l_idx_sal_min) | |
, apex_exec.get_number(l_context, l_idx_sal_max) | |
, apex_exec.get_number(l_context, l_idx_sal_cnt) | |
, apex_exec.get_number(l_context, l_idx_comm_sum) | |
, apex_exec.get_number(l_context, l_idx_comm_avg) | |
, apex_exec.get_number(l_context, l_idx_comm_min) | |
, apex_exec.get_number(l_context, l_idx_comm_max) | |
, apex_exec.get_number(l_context, l_idx_comm_cnt) | |
) | |
); | |
end loop; | |
-- コンテキストを閉じる。 | |
apex_exec.close(l_context); | |
return; | |
-- 必要に応じて例外処理は定義する。 | |
end emp_summary; | |
/ |
SQLワークショップのSQLスクリプトを開きます。
作成を実行します。
コードを貼り付け、適当なスクリププト名を入力して実行をクリックします。