CURSOR_SHARING
ON CONVERSION ERROR
функцията не работи, когато параметърът CURSOR_SHARING е зададен на FORCE. За да избегнете тази грешка, променете параметъра на ниво система, сесия или оператор.
В идеалния случай CURSOR_SHARING трябва да бъде настроен на ТОЧНО за цялата система. Но ако имаме приложение, което не използва свързващи променливи, вероятно не можем да изпълним alter system set cursor_sharing=exact;
.
Параметърът може да бъде зададен на ниво сесия с alter session set cursor_sharing=exact;
, но не винаги е удобно постоянно да променяте параметрите на сесията.
Параметърът може да бъде променен на ниво израз с подсказката 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
Грешка в анализатора/оптимизатора
Както откри @gouessej, има друга потенциална причина за грешката ORA-43918, която не е свързана със споделянето на курсора. Изглежда има грешки при анализиране или оптимизиране, свързани с трансформирането на CASE
и TO_
функции на някои версии на Oracle.
Например, следният SQL оператор е неуспешен на Oracle 18c и 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
Вярвам, че това е грешка при синтактичен анализ или оптимизатор, защото грешката изчезва, ако спрете трансформациите чрез добавяне на предикат като rownum >= 1
. (Когато Oracle види ROWNUM
, той предполага, че резултатите трябва да бъдат показани в определен ред и няма да приложи толкова много трансформации към този блок на заявката.)
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