我想在oracle11g数据库表中插入记录。我正在从java调用一个存储过程。执行存储过程时,我遇到以下错误。
ORA-01843: not a valid month. 我将我的日期从字符串转换为java中的日期,如下所示
date=new SimpleDateFormat("MM/dd/yyyy").parse(visitDate);在我的存储过程中,我有以下insert查询
create or replace PROCEDURE CREATE_VISIT(p_visit_date varchar2)
insert into visit(VISIT_ID,visit_date) values
(frc.SEQ_VISIT.nextval,nvl(to_date(p_visit_date, 'mm/dd/yyyy hh:mi am'),
sysdate));
END CREATE_VISIT;发布于 2014-06-13 06:33:42
您在Java中有一个String。在Java语言中,您可以将其转换为Date。到目前为止,想必一切都很好。
但是,您的过程接受varchar2。因此,在某个时刻,您构造的Date将被显式或隐式地转换为varchar2。您没有说明它是在哪里发生的(在Java或PL/SQL中),也没有说明它是显式还是隐式地完成的。如果转换是在PL/SQL语言中隐式完成的,那么将使用您的会话的NLS_DATE_FORMAT,对于同一数据库中的不同会话,它可能是不同的。在默认的基于US的数据库和客户端安装中,它将是DD-MON-RR。
在您的过程中,然后对使用显式格式掩码传入的字符串调用to_date。如果传入的字符串不是mm/dd/yyyy hh:mi am格式,您将得到一个错误,或者,更糟糕的是,您将得到一个不正确的结果(这是一个老问题,即字符串01/02/03表示2003年1月2日、2003年2月1日还是1901年2月3日)。
如果我们猜测Java语言中的Date是使用会话的默认NLS_DATE_FORMAT DD-MON-YYYY隐式转换为varchar2的,那么我们就可以理解为什么您的to_date转换会失败。例如,如果您的Date为2014年5月30日,它将被隐式转换为字符串"30- May -14“。如果您随后尝试使用to_date和格式掩码mm/dd/yyyy hh:mi am将其转换回date,Oracle将尝试将字符串中30转换为月份,并引发错误,因为没有第30个月。
实际上,你应该从头到尾使用正确的数据类型,并且应该避免像瘟疫一样的隐式强制转换。如果您声明您的过程接受date参数,那么您可以从您的Java代码中传递一个Date,并在您的过程中省略to_date调用。Date将从Java语言传递到PL/SQL语言,而不需要先转换成varchar2,然后再转换回date,这样您就不必担心确保所有的格式掩码在代码库中对齐。
create or replace PROCEDURE CREATE_VISIT(p_visit_date date)
AS
BEGIN
insert into visit(VISIT_ID,visit_date)
values (frc.SEQ_VISIT.nextval,nvl(p_visit_date, sysdate);
END CREATE_VISIT;https://stackoverflow.com/questions/24194618
复制相似问题