当我想将其更改为“日期列类型”时出现错误ORA-01861

时间:2019-05-21 11:09:42

标签: oracle oracle12c

我有一张表,该表根据“日期”列类型计算一些度量。 同样,应该将日期存储为波斯日历,但是最后当我使用TO_DATE函数更改其类型时,在5月的19、20、21天出现了ORA-01861错误,而该日期已经存在,第二个波斯日历的一个月有31天。 这是我的查询:

with a as
 (select to_char(to_date('20190518', 'YYYYMMDD'),
                 'YYYYMMDD',
                 'NLS_CALENDAR=PERSIAN') PERSIAN_DATE
    from DUAL
  UNION ALL
  select to_char(to_date('20190519', 'YYYYMMDD'),
                 'YYYYMMDD',
                 'NLS_CALENDAR=PERSIAN') PERSIAN_DATE
    from DUAL
  UNION ALL
  select to_char(to_date('20190520', 'YYYYMMDD'),
                 'YYYYMMDD',
                 'NLS_CALENDAR=PERSIAN') PERSIAN_DATE
    from DUAL
  UNION ALL
  select to_char(to_date('20190521', 'YYYYMMDD'),
                 'YYYYMMDD',
                 'NLS_CALENDAR=PERSIAN') PERSIAN_DATE
    from DUAL
  UNION ALL
  select to_char(to_date('20190522', 'YYYYMMDD'),
                 'YYYYMMDD',
                 'NLS_CALENDAR=PERSIAN') PERSIAN_DATE
    from DUAL)
SELECT TO_DATE(PERSIAN_DATE, 'YYYY/MM/DD') pers_date FROM A

我的oracle数据库版本是Oracle 12.2.0.1.0

2 个答案:

答案 0 :(得分:1)

将字符串转换为DATE,然后转换为字符串,然后再次转换为DATE,这是没有用的。

尝试这个:

WITH a AS
 (SELECT TO_DATE('20190518', 'YYYYMMDD') PERSIAN_DATE
    FROM DUAL
  UNION ALL
  SELECT TO_DATE('20190519', 'YYYYMMDD') PERSIAN_DATE
    FROM DUAL
  UNION ALL
  SELECT TO_DATE('20190520', 'YYYYMMDD') PERSIAN_DATE
    FROM DUAL
  UNION ALL
  SELECT TO_DATE('20190521', 'YYYYMMDD') PERSIAN_DATE
    FROM DUAL
  UNION ALL
  SELECT TO_DATE('20190522', 'YYYYMMDD') PERSIAN_DATE
    FROM DUAL)
SELECT to_char(PERSIAN_DATE, 'YYYYMMDD', 'NLS_CALENDAR=PERSIAN') pers_date 
FROM A

或更短:

SELECT TO_CHAR(TO_DATE('20190517', 'YYYYMMDD')+LEVEL, 'YYYYMMDD', 'NLS_CALENDAR=PERSIAN') pers_date 
FROM dual
CONNECT BY LEVEL <= 5;

或使用DATE文字和NLS会话值:

ALTER SESSION SET NLS_CALENDAR = 'PERSIAN';
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYYMMDD'; 

SELECT DATE '2019-05-17' + LEVEL pers_date 
FROM dual
CONNECT BY LEVEL <= 5;

答案 1 :(得分:0)

当您仅对第18个(没有问题)执行选择并添加原始值时,您将看到它返回

with a as
     (select to_char(to_date('20190518', 'YYYYMMDD'),
                     'YYYYMMDD',
                     'NLS_CALENDAR=PERSIAN') PERSIAN_DATE
        from DUAL)
    SELECT PERSIAN_DATE, TO_DATE(PERSIAN_DATE, 'YYYY/MM/DD') pers_date FROM A;

Persian Date    pers_date
13980228        28/FEB/98  00:00:00  

因此oracle正在尝试舍弃前两个字符,并确定其余日期的最佳日期(确信这不是正确的波斯日期)。

因此,当您在第19次运行时遵循相同的逻辑(我们只能获取到日期的原始值将出错)

with a as
  (select to_char(to_date('20190519', 'YYYYMMDD'),
                 'YYYYMMDD',
                 'NLS_CALENDAR=PERSIAN') PERSIAN_DATE
    from DUAL)
SELECT PERSIAN_DATE pers_date FROM A;

Persian Date
13980229

按照与上述相同的逻辑,丢弃前两个字符,您得到1998年2月29日……这不是一个有效的日期。

正如其他人在评论中所述,Oracle只是存储它不关心日历的日期,因此您需要转换为适当的日历以进行显示。

有关oracle如何存储日期的详细说明,请参见

How are dates stored in Oracle?