Ошибка ORA-01861, когда я хочу изменить его на «тип столбца даты» - PullRequest
0 голосов
/ 21 мая 2019

У меня есть таблица, которая вычисляет некоторую базу мер по типу столбца Дата.Кроме того, это должно быть сохранение даты в виде персидского календаря, но в конце, когда я использую функцию TO_DATE для изменения ее типа, появляется ошибка ORA-01861 в 19,20,21 днях мая, хотя такая дата уже существует, а втораямесяц персидского календаря имеет 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 ]

1 голос
/ 21 мая 2019

Вы преобразуете жало в ДАТУ, затем в строку и обратно в ДАТУ, это бесполезно.

Попробуйте это:

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;
0 голосов
/ 22 мая 2019

Когда вы выполните выбор только 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  

Итак, оракул пытается отбросить первые два символа и сделать лучшую дату из остальных (почти наверняка это не правильная персидская дата).

Таким образом, следуя той же логике, когда вы запускаете это для 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

Следуя той же логике, что и выше, отбросьте первые два символа, и вы получите 29 февраля 1998 года ... это недопустимая дата.

Как отмечали другие в комментариях, Oracle просто хранит дату, которая не заботится о календаре, вам необходимо преобразовать ее в соответствующий календарь для отображения.

Хорошее объяснение того, как оракул хранит даты, смотрите

Как даты хранятся в Oracle?

...