Oracle
 sql >> Datenbank >  >> RDS >> Oracle

ON CONVERSION ERROR schlägt mit ORA-43918 fehl:Dieses Argument muss ein Literal sein

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