sql >> Databáze >  >> RDS >> Oracle

ON CONVERSION ERROR se nezdaří s ORA-43918:Tento argument musí být doslovný

CURSOR_SHARING

ON CONVERSION ERROR funkce nefunguje, když je parametr CURSOR_SHARING nastaven na FORCE. Chcete-li se této chybě vyhnout, změňte parametr na úrovni systému, relace nebo příkazu.

V ideálním případě by CURSOR_SHARING měla být nastavena na EXACT pro celý systém. Ale pokud máme aplikaci, která nepoužívá proměnné vazby, pravděpodobně nemůžeme spustit alter system set cursor_sharing=exact; .

Parametr lze nastavit na úrovni relace pomocí alter session set cursor_sharing=exact; , ale není vždy vhodné neustále měnit parametry relace.

Parametr lze změnit na úrovni příkazu pomocí nápovědy 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

Chyba analyzátoru/optimalizátoru

Jak zjistil @gouessej, existuje další potenciální důvod chyby ORA-43918, který nesouvisí se sdílením kurzoru. Zdá se, že dochází k chybám analýzy nebo optimalizace související s transformací CASE a TO_ funguje na některých verzích Oracle.

Například níže uvedený příkaz SQL selže na Oracle 18c a 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

Domnívám se, že se jedná o chybu analýzy nebo optimalizátoru, protože chyba zmizí, pokud zastavíte transformace přidáním predikátu jako rownum >= 1 . (Když Oracle uvidí ROWNUM , předpokládá, že výsledky musí být zobrazeny v určitém pořadí a na daný blok dotazu nebude aplikováno tolik transformací.)

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



  1. PHP MySQL INSERT vrátí hodnotu s jedním provedením dotazu

  2. Bash skript pro načtení datového vstupního souboru MySQL

  3. Při použití mezinárodních znaků dostávám duální výsledky z dotazu mysql, tj. Å/Ä=A &Ö=O,

  4. Vyhledávání MySQL s objednanými zástupnými znaky a extrahování jejich hodnot