【问题标题】:ORA-01843: not a valid monthORA-01843: 无效的月份
【发布时间】:2014-08-03 09:09:20
【问题描述】:

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

ORA-01843: not a valid month.  

我在 java 中将日期从字符串转换为日期,如下所示

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;

【问题讨论】:

  • 为什么不为p_visit_date 参数使用真正的DATE

标签: java stored-procedures oracle11g


【解决方案1】:

您在 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 年 2 月 2 日或 2003 年 2 月 1 日或 1901 年 2 月 3 日)。

如果我们猜测 Java 中的 Date 正在使用会话的默认 NLS_DATE_FORMATDD-MON-YYYY 隐式转换为 varchar2,那么我们可以看到为什么您的 to_date 转换会失败。例如,如果您有一个 2014 年 5 月 30 日的 Date,它将被隐式转换为字符串“30-MAY-14”。如果您随后尝试使用to_datemm/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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-04
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-13
    相关资源
    最近更新 更多