CURSOR_SHARING
ON CONVERSION ERROR
パラメータCURSOR_SHARINGがFORCEに設定されている場合、この機能は機能しません。このエラーを回避するには、システム、セッション、またはステートメントレベルでパラメータを変更します。
理想的には、CURSOR_SHARINGはシステム全体でEXACTに設定する必要があります。ただし、バインド変数を使用しないアプリケーションがある場合は、alter system set cursor_sharing=exact;
を実行できない可能性があります。 。
パラメータは、alter session set cursor_sharing=exact;
を使用してセッションレベルで設定できます。 、ただし、セッションパラメータを絶えず変更することが常に便利であるとは限りません。
パラメータは、ヒントCURSOR_SHARING_EXACT
を使用してステートメントレベルで変更できます。 :
SQL> select /*+ cursor_sharing_exact */ to_date(the_date default null on conversion error, 'MM/DD/YYYY') the_date
2 from
3 (
4 select '1/1/2021' the_date from dual union all
5 select 'bad date' the_date from dual
6 );
THE_DATE
---------
01-JAN-21
パーサー/オプティマイザーのバグ
@gouessejが発見したように、カーソル共有とは関係のないORA-43918エラーの別の潜在的な理由があります。 CASE
の変換に関連する解析またはオプティマイザのバグがあるようです およびTO_
一部のバージョンのOracleで機能します。
たとえば、以下のSQLステートメントはOracle18cおよび19cで失敗します。
SQL> select case when v_num is null then 0 else v_num end
2 from
3 (
4 select to_number('120.3' default null on conversion error, '99999D99') as v_num
5 from dual
6 );
select to_number('120.3' default null on conversion error, '99999D99') as v_num
*
ERROR at line 4:
ORA-43918: This argument must be a literal
rownum >= 1
のような述語を追加して変換を停止するとエラーがなくなるため、これは解析またはオプティマイザーのバグだと思います。 。 (OracleがROWNUM
を検出した場合 、結果を特定の順序で表示する必要があり、そのクエリブロックにそれほど多くの変換を適用しないことを前提としています。)
SQL> select case when v_num is null then 0 else v_num end
2 from
3 (
4 select to_number('120.3' default null on conversion error, '99999D99') as v_num
5 from dual
6 where rownum >= 1
7 );
CASEWHENV_NUMISNULLTHEN0ELSEV_NUMEND
------------------------------------
120.3