Oracle Строка Дата до даты возвращения последние 7 дней - PullRequest
1 голос
/ 14 апреля 2020

У меня очень большой набор данных, который я запрашиваю. Более 90 миллионов строк. Я пытаюсь ограничить данные за последние 7 дней, но у меня проблемы с синтаксисом Oracle. База данных Oracle 11g

Поле даты называется START_UTC_DAY. Это строка, которая выглядит как 20200414

Я пытался

 SELECT TO_DATE(START_UTC_DAY, 'YYYYMMDD')
FROM SOURCETABLE
WHERE START_UTC_DAY > SysDate - 7

Я получаю ORA- 01861 Литерал не совпадает со строкой формата

Простите мое невежество, мой SQL находится в зачаточном состоянии, и я учусь, как я go.

Ответы [ 3 ]

3 голосов
/ 14 апреля 2020
SELECT TO_DATE(START_UTC_DAY, 'YYYYMMDD')
FROM SOURCETABLE
WHERE TO_DATE(START_UTC_DAY, 'YYYYMMDD') > SysDate - 7

TO_DATE() в предложении WHERE преобразует строковое значение с заданной моделью формата в тип DATE, прежде чем сравнивать его с другим значением DATE, что позволяет избежать неявного преобразования, вызвавшего проблему. См. Комментарии для лучшего варианта.

Сообщение здесь: избегайте неявных преобразований.

Объяснение:

Ошибка произошла из-за неявного преобразования в предложении WHERE, сравнение между два значения разных типов данных.

2.2.8.2 Неявное преобразование данных

  • При сравнении значения символа со значением DATE, Oracle
    преобразует символьные данные в DATE.

Во время преобразования значение символа / строкового литерала сравнивается с моделью формата даты, которая зависит от следующих настроек.

select name, value from v$parameter where name = 'nls_date_format';

В моей базе данных возвращается,

NAME                 VALUE               
-------------------- --------------------
nls_date_format      DD-MON-YY 

Этот параметр можно изменить на уровне сеанса, что приведет к различным результатам, как показано ниже.

Ниже приведены некоторые тесты для дальнейшего объяснения поведения с помощью SQL Разработчик, использующий новый сеанс.

SQL> show parameter nls_date_format;
NAME            TYPE   VALUE     
--------------- ------ --------- 
nls_date_format string DD-MON-YY 


SQL> 
select str from 
(select '20200412' as str from dual)
where str <> sysdate;

...
Error report -
ORA-01861: literal does not match format string


SQL> 
alter session set nls_date_format = 'ddmmyyyy';

Session altered.

SQL> 
SQL> show parameter nls_date_format;
NAME            TYPE   VALUE    
--------------- ------ -------- 
nls_date_format string ddmmyyyy 


SQL> 
select str from 
(select '20200412' as str from dual)
where str <> sysdate;

...
Error report -
ORA-01843: not a valid month


SQL> 
alter session set nls_date_format = 'fxyyyy-mm-dd';

Session altered.

SQL> 
SQL> show parameter nls_date_format;
NAME            TYPE   VALUE        
--------------- ------ ------------ 
nls_date_format string fxyyyy-mm-dd 


SQL> 
select str from 
(select '20200412' as str from dual)
where str <> sysdate;

...
Error report -
ORA-01861: literal does not match format string


SQL> 
alter session set nls_date_format = 'yyyymmdd';

Session altered.

SQL> 
SQL> show parameter nls_date_format;
NAME            TYPE   VALUE    
--------------- ------ -------- 
nls_date_format string yyyymmdd 


SQL> 
select str from 
(select '20200412' as str from dual)
where str <> sysdate;

STR     
--------
20200412

Как показано выше, один и тот же запрос приводит к разным "результатам" в зависимости от настройки nls_date_format.

1 голос
/ 14 апреля 2020

Поле даты называется START_UTC_DAY, оно является строкой и выглядит как 20200414

Когда вы говорите, что дата выглядит как 20200414, это не означает, что это строка, это просто означает, что Ваши locale-speci c Настройки NLS настроены на отображение даты в этом формате. Но на самом деле он не сохраняется ни в каком формате.

Я получаю, что литерал ORA-01861 не соответствует строке формата

Это потому, что вы используете TO_DATE в дату , поэтому вынуждаете Oracle преобразовать ДАТУ в строку на основе NLS-зависимого формата, а затем выполнить обратное преобразование в дату, используя упомянутый вами формат. Это приводит к ошибке ORA-01861 Literal does not match format string.

Никогда не используйте TO_DATE в столбце даты, используйте TO_CHAR, чтобы отобразить его в желаемом формате:

SELECT TO_CHAR(START_UTC_DAY, 'YYYYMMDD')
FROM SOURCETABLE
WHERE START_UTC_DAY > SYSDATE -7;

Кроме того, также запомните DATE имеет временную часть до секунд. Если вам нужна только часть даты без времени, вам нужно использовать TRUNC(SYSDATE).

0 голосов
/ 14 апреля 2020

Я думаю, вы можете захотеть TO_CHAR() вместо TO_DATE():

SELECT TO_CHAR(START_UTC_DAY, 'YYYYMMDD')
FROM SOURCETABLE
WHERE START_UTC_DAY > SysDate - 7;

Обратите внимание, что sysdate имеет компонент времени. Итак, вы можете захотеть: trunc(sysdate) - interval '7' day (я предпочитаю явный синтаксис interval).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...