ORA-01843: 无效的月份 -java 到 sql 日期转换

Posted

技术标签:

【中文标题】ORA-01843: 无效的月份 -java 到 sql 日期转换【英文标题】:ORA-01843: not a valid month -java to sql date conversion 【发布时间】:2016-06-20 18:48:52 【问题描述】:

我需要将特定时间戳从 java 插入 Oracle 数据库; 我的 oracle 列 ChangeTime 是 DATA_TYPE=TIMESTAMP(6) 并且期望值格式为 - 08-APR-16 09.52.22.000000000 AM。

我已在我的 java 代码中将 java.sql.Timestamp 转换为字符串:

String changeTimestamp = new Timestamp(System.currentTimeMillis()).toString();

我的 SQL PreparedStatement 如下:

    <property name="updatePersonDetail">
        <bean class="com.cigna.ibor.dao.UpdateWithParameters" parent="dao.template">
            <constructor-arg ref="mydb.ds" />
            <constructor-arg>
                <value>
                    <![CDATA[
UPDATE MYDB.INDIV_DETAIL
SET   PERSON_ID =?
    , LAST_OPER_ID = ?
    , LAST_TIMESTMP =  ?,

WHERE SRC_LOC_CD = ?
  AND SRC_SYS_ID = ?
                    ]]>
                </value>
            </constructor-arg>
            <constructor-arg>
                <list>
                    <ref local="java.sql.Types.VARCHAR" />
                    <ref local="java.sql.Types.VARCHAR" />
                    <ref local="java.sql.Types.VARCHAR" />
                    <ref local="java.sql.Types.VARCHAR" />
                    <ref local="java.sql.Types.VARCHAR" />

                </list>
            </constructor-arg>
        </bean>
    </property>

我在运行时收到 java.sql.SQLDataException: ORA-01843: not a valid month。 任何帮助表示赞赏!

【问题讨论】:

看起来您正在尝试将字符串插入时间戳 添加更多代码以及时间戳的一些调试输出会很有帮助。 @kevinsky : 是的...如何转换该字符串,以便我的 oracle 在更新时不会抛出错误? “expects value in the format”表明对 Oracle 如何存储日期和时间戳的误解。如果您确定您的会话设置了该 NLS 格式,那么它可能会起作用,但最好明确说明。为什么要传递时间戳,为什么不使用 Oracle 的 systimestampcurrent_timestamp 来提供值? @AlexPoole:要求是我必须使用特定的时间戳,例如消息第一次得到处理的时间,而不是确切的当前时间戳。 【参考方案1】:

如果您有一个格式类似于08-APR-16 09.52.22.000000000 AM 的字符串,那么您可以指定格式而不是依赖隐式转换:

UPDATE MYDB.INDIV_DETAIL
SET   PERSON_ID =?
    , LAST_OPER_ID = ?
    , LAST_TIMESTMP = TO_TIMESTAMP(?, 'DD-MON-RR HH:MI:SS.FF9 AM'),
WHERE SRC_LOC_CD = ?
  AND SRC_SYS_ID = ?

格式模型必须与您实际传递的内容相匹配。听起来您假设这是会话的 NLS_TIMESTAMP_FORMAT 设置,但错误表明情况并非如此。不要将您的客户端/IDE 显示查询的日期/时间戳的方式与其存储方式混淆 - 没有内在格式,Oracle 使用与显示值完全不同的内部表示。

即使这样,您仍假设 Oracle 会话的数据语言与 Java 值匹配 - 例如,它们都使用英文月份名称。如果您不确定数据库会话的日期语言是什么,但知道 Java 字符串始终是英文,您可以 specify that in the conversion:

    , LAST_TIMESTMP = TO_TIMESTAMP(?, 'DD-MON-RR HH:MI:SS.FF9 AM'
      , 'NLS_DATE_LANGUAGE=ENGLISH'),

如果您有一个 Java 时间戳值当前正在将其转换为该格式的字符串以进行此调用,您可以将其传递为 时间戳,而不是将其转换为字符串或从字符串转换。

【讨论】:

以上是关于ORA-01843: 无效的月份 -java 到 sql 日期转换的主要内容,如果未能解决你的问题,请参考以下文章

ORA-01843 无效的月份

ORA-01843: 无效的月份 - 报告

oracle ORA-01843 无效的月份

错误代码[20001]; ORA-20001:ERROR-ORA-01843:无效月份

ORA-01843: 无效的月份

ORA-01843: 不是一个有效的月份