sql >> Base de Datos >  >> RDS >> Oracle

ON CONVERSION ERROR falla con ORA-43918:este argumento debe ser un literal

CURSOR_COMPARTIR

El ON CONVERSION ERROR la función no funciona cuando el parámetro CURSOR_SHARING está establecido en FORCE. Para evitar este error, cambie el parámetro a nivel de sistema, sesión o declaración.

Idealmente, CURSOR_SHARING debe establecerse en EXACTO para todo el sistema. Pero si tenemos una aplicación que no usa variables de vinculación, probablemente no podamos ejecutar alter system set cursor_sharing=exact; .

El parámetro se puede establecer a nivel de sesión con alter session set cursor_sharing=exact; , pero no siempre es conveniente cambiar constantemente los parámetros de la sesión.

El parámetro se puede cambiar en el nivel de declaración con la sugerencia 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

Error del analizador/optimizador

Como descubrió @gouessej, existe otra posible razón para el error ORA-43918 que no está relacionado con el uso compartido del cursor. Parece que hay errores de análisis o optimización relacionados con la transformación de CASE y TO_ funciona en algunas versiones de Oracle.

Por ejemplo, la siguiente instrucción SQL falla en Oracle 18c y 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

Creo que se trata de un error de análisis o optimización porque el error desaparece si detiene las transformaciones agregando un predicado como rownum >= 1 . (Cuando Oracle ve ROWNUM , asume que los resultados deben mostrarse en un orden determinado y no aplicará tantas transformaciones a ese bloque de consulta).

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