Oracle DateTime в предложении Where?


84

У меня есть sql примерно так:

SELECT EMP_NAME, DEPT
FROM EMPLOYEE
WHERE TIME_CREATED >= TO_DATE('26/JAN/2011','dd/mon/yyyy')

-> Это возвращает 10 строк и TIME_CREATED = '26 -JAN-2011 '

Теперь, когда я делаю это, я не получаю никаких строк назад,

SELECT EMP_NAME, DEPT
    FROM EMPLOYEE
    WHERE TIME_CREATED = TO_DATE('26/JAN/2011','dd/mon/yyyy')

-> Взял больше, чем из

По какой причине?


4
Вам следует избегать языковых форматов даты. Это может вызвать проблемы в разных системах. Вы должны использовать 01вместо JAN(плюс, конечно, формат approriate), чтобы ваш код работал без проблем в любой системе.
a_horse_with_no_name

Ответы:


149

Да: TIME_CREATED содержит дату и время . Используйте, TRUNCчтобы убрать время:

SELECT EMP_NAME, DEPT
FROM EMPLOYEE
WHERE TRUNC(TIME_CREATED) = TO_DATE('26/JAN/2011','dd/mon/yyyy')

ОБНОВЛЕНИЕ:
как указывает Дэйв Коста в комментарии ниже, это не позволит Oracle использовать индекс столбца, TIME_CREATEDесли он существует. Альтернативный подход без этой проблемы:

SELECT EMP_NAME, DEPT
FROM EMPLOYEE
WHERE TIME_CREATED >= TO_DATE('26/JAN/2011','dd/mon/yyyy') 
      AND TIME_CREATED < TO_DATE('26/JAN/2011','dd/mon/yyyy') + 1

14
Обратите внимание, что этот подход предотвратит использование индекса для TIME_CREATED, если он существует.
Дэйв Коста

Спасибо, что разместили решение. Найти его было легко и быстро. Хотя я работал над другими СУБД, такими как Ingres, MS-SQL, MS-Access и DB2, я не работал с Oracle до моего текущего назначения.
Джейсон ТЕПУРТЕН

Почему бы не использовать BETWEEN TO_DATE('26/JAN/2011','dd/mon/yyyy') AND TO_DATE('26/JAN/2011','dd/mon/yyyy') + 1?
ajeh 04

2
@ajeh: Не люблю betweenиз-за двусмысленности. Это звучит так, как будто это исключительные границы, хотя на самом деле это включает. Вот почему я избегаю этого. Более того, в этом конкретном примере все было бы иначе.
Дэниел Хилгарт, 06

28

Вы также можете использовать следующее, чтобы включить часть TIME в свой запрос:

SELECT EMP_NAME
     , DEPT
  FROM EMPLOYEE 
 WHERE TIME_CREATED >= TO_DATE('26/JAN/2011 00:00:00', 'dd/mon/yyyy HH24:MI:SS');


7

Это связано с тем, что DATEстолбец в Oracle также содержит временную часть. Результатом to_date()функции является дата с установленным временем, 00:00:00поэтому она, вероятно, не соответствует ни одной строке в таблице.

Вам следует использовать:

SELECT EMP_NAME, DEPT
FROM EMPLOYEE
WHERE trunc(TIME_CREATED) = TO_DATE('26/JAN/2011','dd/mon/yyyy')

5

Как другие люди прокомментировали выше, использование TRUNC предотвратит использование индексов (если был индекс на TIME_CREATED). Чтобы избежать этой проблемы, запрос можно структурировать как

SELECT EMP_NAME, DEPT
FROM EMPLOYEE
WHERE TIME_CREATED BETWEEN TO_DATE('26/JAN/2011','dd/mon/yyyy') 
            AND TO_DATE('26/JAN/2011','dd/mon/yyyy') + INTERVAL '86399' second;

86399 на 1 секунду меньше количества секунд в сутках.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.