2021年6月8日火曜日

動的にSQLを生成しているレポートでSQLの構文エラーが出るのだけど、どうしたらいい?

 ORA-00907: missing right parenthesisが発生するのだけど、どうすればいい?と聞かれたので、SQLの完全トレースをとって確認したら、と回答しました。

デバッグの完全トレースについては、実際にOracle APEXが実行しているSQLを確認する方法として何度か紹介しています。この記事では、発生しているエラーを確認する方法として、完全トレースを取得する手順を紹介してみます。

例として、以下のPL/SQLコードによって生成したSELECT文でレポートを表示する、クラシック・レポートを作ります。

begin
if :P1_D = 'R' then
return q'~select 1 as a, 2 as b from (select 1 as a, 2 as b from dual)~';
end if;
return q'~select 1 as a, 2 as b from (select 1 as a, 2 as b from dual)~';
end;


このページを実行すると、以下の表示になります。


ここでPL/SQLコードを以下のように変更し、ページ・アイテムP1_DがRのときには、右カッコが足りないSELECT文にします。ページ・デザイナがPL/SQLコードを保存するときにはP1_DをnullとしてPL/SQLコードを評価するため、エラーは発生しません。エラーが発生するのは、アプリケーションの実行時のみです。

begin
if :P1_D = 'R' then
return q'~select 1 as a, 2 as b from (select 1 as a, 2 as b from dual~';
end if;
return q'~select 1 as a, 2 as b from (select 1 as a, 2 as b from dual)~';
end;

アプリケーションを実行すると、構文エラーが発生します。


PL/SQLコードがそれほど長くなくても、実際に生成されるであろうSELECT文を想像するのは大変です。そこで、アプリケーションのデバッグを有効にして、実際に実行されているSELECT文を確認します。

開発者ツール・バーの右端にある歯車アイコンより、デフォルト・デバッグ・レベルを開き、完全トレースを選択します。


開発者ツール・バーのデバッグ(完全トレース)をクリックし、デバッグを有効にします。デバッグが有効になると、開発者ツール・バーの表示はデバッグなしに変わります。


アプリケーションより、エラーが発生する処理を実行します。今回の例で言うと、レポートの表示なので、再表示を行うためにページをリロードします。

デバッグ、特に完全トレースを有効にすると操作が極端に遅くなります。ログを取得したら開発者ツール・バーのデバッグなしをクリックし、デバッグを解除します。

取得したログを参照するため、デバッグの表示をクリックします。


デバッグ画面より、対象の処理のログを見つけてビュー識別子をクリックします。

ページ番号の条件には注意が必要です。レポートとフォームの組み合わせの場合、データの更新処理はフォームのページに登録されたプロセスが実行します。フォームの処理が終わるとレポートのページに戻ります。レポートのページ上でデバッグの表示を実行すると、ページの条件は、現在表示されているレポートのページ番号になります。そのため、別のページであるフォームのページに紐づくビュー識別子は一覧に表示されません。ページ番号の検索条件をレポートではなく、フォームのページ番号に変更する必要があります。

今回の対象はレポートのページなので、ページの検索条件の変更は不要です。


記録されたメッセージの一覧が表示されます。


エラーが発生した箇所を探します。対話モード・レポートの検索ボックスで検索すると、検索に一致したメッセージが取り出されますが、その前後の行は表示されません。そのため、私はブラウザによる検索を主に使用しています。


実際に実行しているSELECT文を確認することで、なぜ構文エラーが発生したのか調査を進められます。

以上になります。

非常に簡単なものですが、今回の作業の確認に使用したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/generate-error.sql

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