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')

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

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

Sanjeev40084
источник
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');
Давидс
источник
8

Вы также можете:

SELECT EMP_NAME, DEPT
FROM EMPLOYEE
WHERE TRUNC(TIME_CREATED) = DATE '2011-01-26'
Матас Вайткявичюс
источник
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')
a_horse_with_no_name
источник
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 секунду меньше количества секунд в сутках.

Basanth Roy
источник