CURSOR_SHARING
Der ON CONVERSION ERROR
Die Funktion funktioniert nicht, wenn der Parameter CURSOR_SHARING auf FORCE gesetzt ist. Um diesen Fehler zu vermeiden, ändern Sie den Parameter auf System-, Sitzungs- oder Anweisungsebene.
Idealerweise sollte CURSOR_SHARING für das gesamte System auf EXACT gesetzt werden. Aber wenn wir eine Anwendung haben, die keine Bind-Variablen verwendet, können wir alter system set cursor_sharing=exact;
wahrscheinlich nicht ausführen .
Der Parameter kann auf Sitzungsebene mit alter session set cursor_sharing=exact;
gesetzt werden , aber es ist nicht immer praktisch, Sitzungsparameter ständig zu ändern.
Der Parameter kann auf Anweisungsebene mit dem Hinweis CURSOR_SHARING_EXACT
geändert werden :
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
Parser-/Optimiererfehler
Wie @gouessej feststellte, gibt es einen weiteren möglichen Grund für den Fehler ORA-43918, der nichts mit der Cursorfreigabe zu tun hat. Es scheinen Parsing- oder Optimiererfehler im Zusammenhang mit der Umwandlung von CASE
zu geben und TO_
funktioniert auf einigen Versionen von Oracle.
Beispielsweise schlägt die folgende SQL-Anweisung auf Oracle 18c und 19c fehl:
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
Ich glaube, dass dies ein Parsing- oder Optimierungsfehler ist, da der Fehler verschwindet, wenn Sie Transformationen stoppen, indem Sie ein Prädikat wie rownum >= 1
hinzufügen . (Wenn Oracle ROWNUM
sieht , geht es davon aus, dass die Ergebnisse in einer bestimmten Reihenfolge angezeigt werden müssen und wendet nicht so viele Transformationen auf diesen Abfrageblock an.)
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