我想在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;
答案 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;