admin

Liquibase脚本返回ORA-01843:无效月份

sql

我在以下liquibase脚本中遇到麻烦:

<sql>
        MERGE INTO A config
        USING (SELECT 100 as id, '02.01.15 12:00:00' as CHANGED, 0 as DELETED, 1 as B FROM DUAL) src ON (src.id = config.id)
        WHEN NOT MATCHED THEN 
            INSERT(id,CHANGED, DELETED, B) VALUES(src.id, src.CHANGED, src.DELETED, src.B)
        WHEN MATCHED THEN
            UPDATE SET config.B = src.B;
 </sql>

当我在sql标记之间插入原始代码并在数据库下运行(在SQL Developer中)时,结果是:合并了1行。

当我通过liquibase运行它时,出现错误 ORA-01843:不是有效月份

这怎么可能?


阅读 205

收藏
2021-07-01

共1个答案

admin

'02.01.15 12:00:00'不是日期,而是字符串;如果您尝试将其插入DATE数据类型列,则Oracle将尝试使用以下等效项将其转换为日期:

SELECT TO_DATE(
         '02.01.15 12:00:00',
         ( SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT' )
       ) as CHANGED
FROM   DUAL

因此,如果您的NLS_DATE_FORMAT会话参数与字符串的格式不匹配,'02.01.15 12:00:00'则它将引发异常-
这是自获取以来似乎正在发生的事情ORA-01843: not a valid month

最好的解决方案是修改脚本以将字符串显式转换为日期:

MERGE INTO A config
USING (
  SELECT 100 as id,
         TO_DATE( '02.01.15 12:00:00', 'DD.MM.YY HH24:MI:SS' ) as CHANGED,
         0 as DELETED,
         1 as B
  FROM   DUAL
) src ON (src.id = config.id)
WHEN NOT MATCHED THEN 
  INSERT(id,CHANGED, DELETED, B) VALUES(src.id, src.CHANGED, src.DELETED, src.B)
WHEN MATCHED THEN
  UPDATE SET config.B = src.B;

或使用时间戳文字: TIMESTAMP '2015-01-02 12:00:00'

但是您也可以创建一个登录触发器来更改NLS_DATE_FORMAT会话参数。将触发器包装在以下代码周围:

ALTER SESSION SET NLS_DATE_FORMAT = 'DD.MM.YY HH24:MI:SS';

但是,这会将所有隐式转换中使用的日期格式从字符串更改为日期(反之亦然),因此可能会中断其他也依赖于此类隐式转换的查询。此外,每个用户都可以随时更改其会话参数,因此在登录时设置此默认值取决于他们在会话期间永不更改它。

[TL; DR] 修复您的脚本,使其不使用数据类型之间的隐式转换,而不是修改用于隐式转换的格式模型。

2021-07-01