CURSOR_SHARING
De ON CONVERSION ERROR
functie werkt niet wanneer de parameter CURSOR_SHARING is ingesteld op FORCE. Om deze fout te voorkomen, wijzigt u de parameter op systeem-, sessie- of instructieniveau.
Idealiter zou CURSOR_SHARING voor het hele systeem op EXACT moeten worden ingesteld. Maar als we een toepassing hebben die geen bindvariabelen gebruikt, kunnen we waarschijnlijk niet alter system set cursor_sharing=exact;
uitvoeren .
De parameter kan op sessieniveau worden ingesteld met alter session set cursor_sharing=exact;
, maar het is niet altijd handig om sessieparameters voortdurend te wijzigen.
De parameter kan op instructieniveau worden gewijzigd met de hint 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
Parser/optimizer-bug
Zoals @gouessej ontdekte, is er nog een andere mogelijke reden voor de ORA-43918-fout die geen verband houdt met het delen van de cursor. Er lijken parseer- of optimalisatiefouten te zijn met betrekking tot het transformeren van CASE
en TO_
functies op sommige versies van Oracle.
De onderstaande SQL-instructie mislukt bijvoorbeeld op Oracle 18c en 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
Ik geloof dat dit een parseer- of optimalisatiefout is, omdat de fout verdwijnt als je transformaties stopt door een predikaat toe te voegen zoals rownum >= 1
. (Als Oracle ROWNUM
ziet , het gaat ervan uit dat de resultaten in een bepaalde volgorde moeten worden weergegeven en zal niet zoveel transformaties toepassen op dat queryblok.)
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