【问题标题】:Liquibase script returns ORA-01843: not a valid monthLiquibase 脚本返回 ORA-01843:不是有效月份
【发布时间】:2017-12-13 19:54:54
【问题描述】:

以下 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: not a valid month

这怎么可能?

【问题讨论】:

    标签: sql oracle liquibase


    【解决方案1】:

    '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] 修复您的脚本,使其不使用数据类型之间的隐式转换,而不是修改用于隐式转换的格式模型。

    【讨论】:

      【解决方案2】:

      使用这个脚本:

      <sql>
          MERGE INTO A config
          USING (SELECT 100 as id, TO_DATE('2015/02/01 12:00:00','YYYY/MM/DD 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;
      </sql>
      

      【讨论】:

      • 好的,它会工作,但有什么选项可以在不更改脚本的情况下做到这一点?
      猜你喜欢
      • 1970-01-01
      • 2015-07-04
      • 1970-01-01
      • 2012-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-23
      • 2014-02-05
      相关资源
      最近更新 更多