ORA-01843:不是有效月份

时间:2014-06-12 22:02:14

标签: java stored-procedures oracle11g

我想在oracle11g数据库表中插入记录。我从java调用存储过程。 执行存储过程时,我收到以下错误。

ORA-01843: not a valid month.  

我在java中将我的日期从String转换为Date,如下所示

date=new SimpleDateFormat("MM/dd/yyyy").parse(visitDate);

在我的存储过程中,我有以下插入查询

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;

1 个答案:

答案 0 :(得分:2)

Java中有String。您将其转换为Java中的Date。到目前为止,大概是这么好。

但是,您的程序接受varchar2。因此,在某些时候,您构造的Date被显式或隐式地强制转换为varchar2。你不会说它发生在哪里(在Java或PL / SQL中),或者它是显式地还是隐式地完成。如果转换是在PL / SQL中隐式完成的,则会使用您的会话NLS_DATE_FORMAT,这对于同一数据库中的不同会话可能会有所不同。在基于美国的默认数据库和客户端安装中,这将是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是使用您的会话varchar2的默认NLS_DATE_FORMAT隐式转换为DD-MON-YYYY,那么我们可以看到为什么to_date转换会失败。例如,如果您有一个2014年5月30日的Date,则会隐式转换为字符串" 30-MAY-14"。如果您尝试使用date并使用格式掩码to_date将其强制转换为mm/dd/yyyy hh:mi am,则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;