2つのページ・アイテムがあり、それぞれタイプがシャトルとなっています。このページ・アイテムには親子関係があり、親となるシャトルで選択した値に基づき、子のシャトルで選択できる値が決まります。
サンプル・データセットのEMP/DEPTをデータ・ソースとして使い、以下のようなページを作成します。
基本の実装
親のシャトルがP1_DEPTNOとして作成されています。表DEPTからDEPTNOを複数選択します。
LOVのSQL問合せは以下になります。
select dname d, deptno r from dept
従業員を選択する子であるシャトルはP1_EMPNOとして作成されています。
LOVのSQL問合せは以下になります。カスケードLOVの親アイテムとしてP1_DEPTNOを指定します。親アイテムとして指定したアイテムは必ず送信されるため、送信されるアイテムに指定する必要はありません。
ページ・アイテムに複数の値が設定される場合、それぞれの値は':'(コロン)で区切られます。そのため、P1_DEPTNOの値をapex_string.splitを呼び出して分割しています。
ページ・アイテムP1_DEPTNOのシャトルで選択した部門の従業員に限り、P1_EMPNOのシャトルで選択できるようになります。
ここまでが基本の実装です。
SQLを記述できない場合
従業員の表がそれぞれ部門で分割されているケースを想定します。
create table emp_accounting as select * from emp where deptno = 10;
create table emp_research as select * from emp where deptno = 20;
create table emp_sales as select * from emp where deptno = 30;
create table emp_operations as select * from emp where deptno = 40;
部門ごとに4つの表が作られています。EMP_ACCOUNTING、EMP_RESEARCH、EMP_SALES、EMP_OPERATIONSです。親となるシャトルではこれらの表を選択し、子となるシャトルは選択された表から従業員を選択します。
親のシャトルのSQL問合せは以下に変わります。
select dname d, 'EMP_' || dname r from dept
ページ・アイテムP3_DEPTNOはコロンで区切られた表名を複数持ちます。
子のシャトルでは、LOVのタイプをSQL問合せを返すファンクション本体に変更し、SQL問合せを戻すPL/SQLファンクション本体として以下を記述します。ファンクションの評価時はページ・アイテムP3_DEPTNOはnullになります。評価に失敗するため、0行を返すダミーのSELECT文を戻しています。
カスケードLOVは基本と同じ設定になります。
動的にSELECT文を作成できない場合
動的にSQLを作る場合でも、最終的には実行可能なSELECT文が生成される必要があります。SELECT文を作るのが困難なケース(RESTサービスを呼び出すなど)では、パイプライン表関数を作成することで対応できる場合もあります。
今回の例を実装すると、以下のようになります。
作成したパイプライン表関数get_cascade_lov_sourceを使用したSQL問合せは以下になります。
select display_value, return_value from table(get_cascade_lov_source(:P2_DEPTNO))
パイプライン表関数による実装の場合、表示値と戻り値を返せばよいので実際のデータ・ソースが表である必要はありません。
カスケードLOVの親アイテムを指定できない場合
あまり無いとは思いますが、カスケードLOVの親アイテムを設定できない場合を考えてみます。
この場合、親となるページ・アイテムが変更されたときに、子となるページ・アイテムをリフレッシュする必要があります。
ページ・アイテムの変更イベントでページ・アイテムのリフレッシュを実行します。このTRUEアクションは、一般的なリフレッシュの設定です。
子アイテムのLOVのSQL問合せ、または、ファンクション本体に親アイテムであるページ・アイテムがバインド変数として使用されている場合、カスケードLOVの親アイテムを指定せずに、送信するページ・アイテムを指定する方法はありません。
このため、親となるページ・アイテムのセッション・ステートのストレージをセッションごと(永続)に切り替えます。
TRUEアクションを作成し、子であるページ・アイテムをリフレッシュする前に配置します。
アクションにサーバー側のコードを実行を選択します。PL/SQLコードは不要なのでnull;とします。送信するアイテムとして親となるページ・アイテムを指定します。
セッション・ステートの定義はセッション(永続)になっているため、送信されたページ・アイテムの値はデータベースに保存されます。子アイテムのソースとなるコードが実行される際に、サーバーに保存されている値がバインド変数に割り当てられるため、親アイテムの値が反映された結果が得られます。
今回の記事は以上です。
https://github.com/ujnak/apexapps/blob/master/exports/cascade-shuttle-lov-source.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完