こちらの記事で自動DMLプロセスの行のロックにPL/SQLコードを記述しても、実行されないようだ、と説明しました。その点について、さらに調べて確認しました。
結果としては、対話グリッドについては期待通り動作しました。フォームは、現在のところ、PL/SQLコードは実行されません。
対話グリッドでは動作するので、確認してみました。以下、作業ログです。
検証に使用したアプリケーションのエクスポートを以下に置いています。
https://github.com/ujnak/apexapps/blob/master/exports/lockrowplsqlcode.sql
サンプル・データセットのEMP/DEPTに含まれる表EMPを使っています。表EMPから対話モード・レポートとフォームのページを作成し、それに加えて、対話グリッドのページを作成しています。
対話グリッドの行の自動処理(DML)のプロセスの行のロックをPL/SQL Codeに切り替え、以下のコードを記述します。
for update nowaitなので、行がロック済みであればORA-54が発生し、ロックの待機は行いません。
実際に表EMPにロックをかけた上で、対話グリッドから保存を実行するとORA-54が発生することが確認できます。
指定した秒数だけロックを待機するよう、コードを書き換えます。10秒だけ待ちます。
対話グリッドから変更を保存してみます。指定した秒数だけ待機したのち、エラーが発生します。発生したエラーはORA-54ではなく、ORA-30006 resource busy; acquire with WAIT timeout expiredです。
最後にfor updateのみ指定し、ずっと待機する動作を確認してみます。
対話グリッドから変更を保存してみます。Saveをクリックすると待機が始まり、ずっと待機します。
待機しているセッションが実行しているSQLを確認します。
SQL> select sql_text from v$sql
2 where sql_id in
3 (
4 select sql_id from v$session
5 where sid in
6 (
7 select waiting_session from dba_waiters
8 )
9 );
SQL_TEXT
--------------------------------------------------------------------------------
SELECT * FROM EMP WHERE EMPNO = :B1 FOR UPDATE
SQL>
今度はUPDATE文ではなく、行のロックに記述したPL/SQLコード内で実行されているSELECT文で待機していることがわかります。
これで現行の対話グリッドでは、FSP_DML_LOCK_ROWやAPEX_DML_LOCK_WAIT_TIMEによる効果を、行のロックとしてPL/SQL Codeを選んで、PL/SQLコードを記述することによって達成できることがわかります。
以上です。
Oracle APEXによるアプリケーション作成の参考になれば幸いです。
完