我在使用以下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:无效月份。
怎么可能?
答案 0 :(得分: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] 修复您的脚本,不要在数据类型之间使用隐式转换,而不是修改用于隐式转换的格式模型。
答案 1 :(得分:0)
使用此脚本:
<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>