【问题标题】:java.sql.SQLException: ORA-01843: not a valid monthjava.sql.SQLException: ORA-01843: 不是一个有效的月份
【发布时间】:2012-03-23 20:17:27
【问题描述】:

在我的 oracle 数据库中插入数据时出现以下错误。

java.sql.SQLException: ORA-01843: not a valid month

数据库中的日期为:dd-MMM-yy (06-MAR-12)
我正在通过以下方法将 06-03-2012 转换为 dd-MMM-yy:

String s="06-03-2012";

String finalexampledt = new SimpleDateFormat("dd-MMM-yy").format(new SimpleDateFormat("dd-MM-yyyy").parse(s));

所以我得到了 12 年 3 月 6 日,这与上述数据库日期格式相同,但我仍然收到错误消息。我插入为:

在 index.jsp 中

 String todaydate="";

Calendar calendar1 = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
todaydate = dateFormat.format(calendar1.getTime());

<input type="text" name="datename" value="<%=todaydate%>"/>

在 servlet(doPost) 中

String s=request.getParameter("datename");

PreparedStatement ps=con.prepareStatement("insert into tablename(rest_dt, othercolname) values (to_date(?, 'dd-mm-yyyy'), ?)");

ps.setString(1, s);
ps.setString(2, otherstringdata);

int  rs=ps.executeUpdate();

有什么建议

【问题讨论】:

  • 什么类型的列有这个日期?日期类型?
  • oracle 中的日期类型列
  • 如何将值插入数据库?
  • @student:你确定你输入的日期总是像 dd-MM-yyyy (英国/法国格式),而不是 MM-dd-yyyy (美国格式)吗?该输入中是否存在不是日期的内容?
  • 你能给我们看看java代码吗?

标签: java sql oracle date


【解决方案1】:

java.time 和 JDBC 4.2

不要将日期作为字符串传入或传出数据库。传输适当的日期对象。我假设您的 JDBC 驱动程序至少兼容 JDBC 4.2。这些天几乎所有的司机。在这种情况下,LocalDate 是用于日期的类型,无论是在您的 Java 程序中还是在向数据库的传输中。

所以你基本上需要的是这样的:

    LocalDate date = LocalDate.of(2012, Month.MARCH, 6);

    PreparedStatement ps = con.prepareStatement(
            "insert into tablename(rest_dt, othercolname) values (?, ?)");

    ps.setObject(1, date);
    ps.setString(2, otherstringdata);

    int rs = ps.executeUpdate();

如果您从 JSP 接收作为字符串输入的日期,请立即将其解析为 LocalDate 对象。无需等到需要将其放入数据库。

    String inputString = "06-03-2012"; // Meaning 6 March 2012
    LocalDate date = LocalDate.parse(inputString, DATE_PARSER);

我一直在使用这个格式化程序:

private static final DateTimeFormatter DATE_PARSER
        = DateTimeFormatter.ofPattern("dd-MM-uuuu", Locale.ROOT);

链接

【讨论】:

    【解决方案2】:

    在 Java 中运行大查询(多重联合)时面临同样的问题,但实际输入没有问题,因为我已经正确转换了 to_date('30-06-2021', 'dd-MM-yyyy') 并发现问题是查询中的 date1。

    例如

    select a,b,c from table1 where date1='31/12/2015'and date2=<actual input>
    union
    select a,b,c from table2 where date1='31/12/2015'and date2=<actual input>
    union
    select a,b,c from table3 where date1='31/12/2015'and date2=<actual input>
    .
    .
    

    date1 也应该转换为to_date,如下所示

    例如

    select a,b,c from table1 where date1=to_date('31/12/2015', 'dd-MM-yyyy') and date2=<actual input>
    

    因此问题已解决。我的建议是,如果您遇到此类问题,请检查查询中的日期部分并使用to_date 提及。

    Java 代码:

    @Autowired
    private NamedParameterJdbcTemplate namedJdbcTemplate;
    
    List<ResponseDTO> list = new ArrayList<>();
    MapSqlParameterSource params = new MapSqlParameterSource();
    params.addValue("value1", dto.getValue1());
    params.addValue("value2", dto.getValue2());
    
    list = namedJdbcTemplate.query(SQL_QUERY, params, new CustomValueMapper());
    

    这纯粹是我自己的经验。如果有帮助,请点击投票。

    【讨论】:

      【解决方案3】:

      问题是 oracle 使用 NLS_DATE_LANGUAGE 来获取当前月份的名称。所以你应该这样做

      select * from nls_session_parameters
      

      并检查您是否有正确的值。您还可以检查以下选择您获得的月份名称

      select  TO_CHAR(TO_DATE('01-03-01', 'DD-MM-YY'), 'MON') from dual
      

      我真的不明白你为什么将变量作为字符串值插入。只需在 java 中使用日期类型(在客户端进行转换)并插入它而不进行转换。如果您真的想将其作为字符串插入,我会使用转换为 dd-MM-yyyy 之类的东西并使用 TO_DATE(, 'DD-MM-YYYY') 插入它。

      编辑:

      在客户端做日期的转换并使用

      ps.setDate(2, <yourDate>);
      

      【讨论】:

      • 那么您对我发布的查询的输出是什么?
      • 不会出现同样的错误,我已经更新了我的问题并给出了详细信息,请参阅
      • 我在ps中使用to_date(),是否需要再次将s转换为日期类型?
      • 我会在客户端进行转换,因为您保存了到数据库的往返。当您的用户输入不正确的日期格式时,将调用数据库并引发异常。之后,您向您的用户显示错误并让他更正他的输入,然后您再次将信息发送到数据库。如果您直接在客户端上进行转换,您可以更快地做出反应。但是,如果您想这样做:您是否查看了将查询设置为的变量的值?
      【解决方案4】:

      rest_dt 列的数据类型是DATE,因此您需要提供一个。您可以使用TO_DATE 函数将字符串转换为Oracle DATE,因此您的插入语句

      insert into tablename(rest_dt, othercolname) values (to_date(?, 'dd-mm-yyyy'), ?)

      没问题。

      只需确保绑定到第一个 ? 变量的字符串值的格式为 dd-mm-yyyy。并且不要自己转换或格式化该值:TO_DATE 函数会完成该部分。

      这里不需要像 nls_date_language 这样的会话设置,因为您明智地选择使用带有 MM 掩码(而不是 MON)的月份的语言不可知设置。

      问候,
      抢。

      【讨论】:

      • 你同样的错误来了,我已经更新了我的问题并给出了详细信息,请参阅
      • 请删除所有转换日期的代码。您写道:“我正在将 06-03-2012 转换为 ...”。只是不要这样做,并将 06-03-2012 提供给您的插入语句。
      【解决方案5】:

      就这样吧

      ("insert into mytablename (rest_dt) values to_date(?, 'DD-MM-YYYY')");  
      

      试试这个

      TO_DATE(?, 'DD-MM-YYYY','NLS_DATE_LANGUAGE = American')  
      

      // 来自Oracle docs

      【讨论】:

      • 是的,但我有更多字段,包括日期
      • 你使用@user1143825 的想法和-setString(1, "06-03-2012") 吗?
      • 是的,我试过了,但同样的异常即将到来,我的插入代码有什么问题吗?我已经在我的问题中发布了
      • @user1143825 ya同样的错误来了,我已经更新了我的问题并给出了详细信息,请参阅
      猜你喜欢
      • 1970-01-01
      • 2015-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-07
      • 2022-01-22
      • 1970-01-01
      相关资源
      最近更新 更多