ORA-01841 :(full) year 必须在 -4713 和 +9999 之间,并且在使用 DBMS_SQL 绑定到动态 sql 时不能为 0

Posted

技术标签:

【中文标题】ORA-01841 :(full) year 必须在 -4713 和 +9999 之间,并且在使用 DBMS_SQL 绑定到动态 sql 时不能为 0【英文标题】:ORA-01841 :(full) year must be between -4713 and +9999, and not be 0 when binding to dynamic sql with DBMS_SQL 【发布时间】:2014-04-02 16:12:54 【问题描述】:

当我运行时(此处为 sn-ps):

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,因为函数名称、类型和参数数量在运行时是已知的。

有什么想法吗?

【问题讨论】:

我运行了一个没有错误的更简单的测试用例。就是这个 sql:“DBMS_SQL.PARSE(curs, 'select :1 from dual', DBMS_SQL.NATIVE);”和相同的绑定参数和数据类型。奇怪的。你可以试试吗? other_package.some_function 的声明是什么?如果你交换了时间戳(或日期)和 varchar2 参数,如果 varchar2 值和 NLS_DATE_FORMAT 是合适的值,我可以想象你会得到这个。因此,您绑定的其他值也可能提供信息。 感谢您的合作,特别感谢 OldProgrammer 从不同的角度看待代码 - 它有帮助。 【参考方案1】:

谢谢@OldProgrammer! 当我尝试按照您的建议运行简单的 sn-p 时,我意识到了一些事情。 问题出在这一行: t_cmd := '开始 :1 := other_package.some_function(:0,:1,:2);结束;';

我没有从这个片段更改绑定名称:“begin :1”,现在我有两个绑定到相同的值。 在立即执行中没关系,因为绑定的顺序很重要,dbms_sql 使用绑定的名称。 来自 some_function(:0,:1,:2) 的参数 :1 也是时间戳。 some_function 返回 varchar2,因此在尝试将结果替换为第一个 ":1" 时发生错误。

我将函数调用改为:

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

并且“ORA-01841 :(full) year must be between -4713 and +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);

现在一切正常。

【讨论】:

以上是关于ORA-01841 :(full) year 必须在 -4713 和 +9999 之间,并且在使用 DBMS_SQL 绑定到动态 sql 时不能为 0的主要内容,如果未能解决你的问题,请参考以下文章

错误 ORA-01841:(完整)年份必须介于 -4713 和 +9999 之间,并且在使用 yyyymmdd 格式加载数据时不能为 0

错误 ORA-01841:在文件中传递出生日期时

oracle 全年度值没有为零 为啥还出 ora-01841

不在 GROUP BY 中,包含 DAY、MONTH、YEAR [重复]

为啥我必须初始化一个数组?

R语言merge函数全连接dataframe数据(Full (outer) join)merge函数进行全连接必须将参数all设置为true(all=TRUE)默认merge函数通过公共列名合并数