ORA-01841: (полный) год должен быть между -4713 и +9999 и не быть 0 при привязке к динамическому sql с DBMS_SQL

Когда я бегу (фрагменты здесь):

t_cmd := 'begin :1 := other_package.some_function(:0,:1,:2); end;';
l_tmstmp timestamp_unconstrained := to_timestamp('1999-07-07 07:07:07.000000000',
'YYYY-MM-DD HH24:MI:SS.FF9');

DBMS_SQL.PARSE(curid, t_cmd, DBMS_SQL.NATIVE);
-- binding here other attributes
DBMS_SQL.BIND_VARIABLE(curid, ':2',  l_tmstmp);
ret := DBMS_SQL.EXECUTE(curid);

Я всегда получаю сообщение об ошибке, даже когда пытаюсь связать простую метку времени, метку времени из varchar2 (TO_TIMESTAMP('timestamp_in_proper_format'), 'YYYY-MM-DD HH24:MI:SS.FF9')) :

ORA-01841 :(full) year must be between -4713 and +9999, and not be 0
ORA-06512: przy linia 1
ORA-06512: przy "SYS.DBMS_SQL", line 1825
ORA-06512: przy "MY_PACKAGE", line where is :

ret := DBMS_SQL.EXECUTE(curid);

Что интересно, проблема не возникает при отладке пакета. Я попытался скомпилировать свой пакет:

 ALTER PACKAGE my_package COMPILE DEBUG PACKAGE;

но проблема все еще возникает, кроме того, в производственной среде она будет скомпилирована с уровнем оптимизации, поэтому я не могу сделать это таким образом. Кроме того, я не могу использовать EXECUTE IMMEDIATE, потому что имя функции, типы и количество параметров известны во время выполнения.

Есть идеи?


person rtbf    schedule 02.04.2014    source источник
comment
Я провел более простой тестовый пример без ошибок. Просто этот sql: DBMS_SQL.PARSE(curs, 'выбрать: 1 из двойного', DBMS_SQL.NATIVE); и тот же параметр привязки и тип данных. Странный. Можешь попробовать?   -  person OldProgrammer    schedule 02.04.2014
comment
Что такое декларация для other_package.some_function? Я мог бы представить, что вы получите это, если бы вы поменяли местами метку времени (или дату) и аргументы varchar2, если бы значение varchar2 и NLS_DATE_FORMAT были подходящими значениями. Таким образом, другие значения, которые вы связываете, также могут быть информативными.   -  person Alex Poole    schedule 02.04.2014
comment
спасибо за сотрудничество, особенно спасибо OldProgrammer, посмотрите на код под другим углом - помогло.   -  person rtbf    schedule 03.04.2014


Ответы (1)


Спасибо, @OldProgrammer! Когда я попытался запустить простой фрагмент, как вы предложили, я кое-что понял. Проблема была в этой строке: t_cmd := 'begin :1 := other_package.some_function(:0,:1,:2); конец;';

Я не изменил имя привязки из этого фрагмента: «begin: 1», и теперь у меня есть две привязки к одному и тому же значению. При немедленном выполнении все было в порядке, потому что ПОРЯДОК привязок имеет значение, dbms_sql использует имена привязок. Аргумент :1 из some_function(:0,:1,:2) также является отметкой времени. some_function возвращает varchar2, поэтому возникали ошибки, когда она пыталась заменить результат на первый ":1".

Я изменил вызов функции на:

t_cmd := 'begin :my_result := other_package.some_function(:0,:1,:2); end;';

И "ORA-01841: (полный) год должен быть между -4713 и +9999" больше не используется.

Я не стал заострять внимание на этом фрагменте "begin :1 :=", т.к. пытался получить результат от такой функции:

ret := DBMS_SQL.EXECUTE(curid);  
src_cur := DBMS_SQL.TO_REFCURSOR(curid);
FETCH src_cur INTO my_result;  
CLOSE src_cur;

но таким образом получение результата из функции не сработало (произошли другие ошибки)

Наконец, я изменил приведенный выше код на:

ret := DBMS_SQL.EXECUTE(curid);
DBMS_SQL.VARIABLE_VALUE(curid, 'my_result', my_result);  
DBMS_SQL.CLOSE_CURSOR(curid);

И теперь все работает нормально.

person rtbf    schedule 03.04.2014