¿Oracle DateTime en la cláusula Where?

84

Tengo sql algo como esto:

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

-> Esto devuelve 10 filas y TIME_CREATED = '26 -JAN-2011 '

Ahora, cuando hago esto, no recupero ninguna fila,

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

-> Sacó lo más grande que fuera

¿Alguna razón por la que?

sanjeev40084
fuente
4
Debe evitar los formatos de fecha que dependen del idioma. Eso puede causar problemas en diferentes sistemas. Debería usar en 01lugar de JAN(más el formato apropiado, por supuesto) para asegurarse de que su código se ejecute sin problemas en cualquier sistema.
a_horse_with_no_name

Respuestas:

149

Sí: TIME_CREATED contiene una fecha y una hora . Úselo TRUNCpara quitar el tiempo:

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

ACTUALIZACIÓN:
Como Dave Costa señala en el comentario a continuación, esto evitará que Oracle use el índice de la columna TIME_CREATEDsi existe. Un enfoque alternativo sin este problema es este:

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
Daniel Hilgarth
fuente
14
Tenga en cuenta que este enfoque evitará el uso de un índice en TIME_CREATED, si existe.
Dave Costa
Gracias por publicar la solución. Fue rápido y fácil de encontrar. Si bien he trabajado en otros DBMS como Ingres, MS-SQL, MS-Access y DB2, no he trabajado con Oracle antes de mi asignación actual.
Jason TEPOORTEN
¿Por qué no usar BETWEEN TO_DATE('26/JAN/2011','dd/mon/yyyy') AND TO_DATE('26/JAN/2011','dd/mon/yyyy') + 1?
ajeh
2
@ajeh: No me gusta betweenpor la ambigüedad. Suena como si fuera exclusivo de los límites cuando en realidad es inclusivo. Por eso lo evito. Además, en este ejemplo concreto, no sería lo mismo.
Daniel Hilgarth
28

También puede utilizar lo siguiente para incluir la parte de TIEMPO en su consulta:

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

También puedes hacer:

SELECT EMP_NAME, DEPT
FROM EMPLOYEE
WHERE TRUNC(TIME_CREATED) = DATE '2011-01-26'
Matas Vaitkevicius
fuente
7

Esto se debe a que una DATEcolumna en Oracle también contiene una parte de tiempo. El resultado de la to_date()función es una fecha con la hora establecida en 00:00:00y, por lo tanto, probablemente no coincida con ninguna fila de la tabla.

Deberías usar:

SELECT EMP_NAME, DEPT
FROM EMPLOYEE
WHERE trunc(TIME_CREATED) = TO_DATE('26/JAN/2011','dd/mon/yyyy')
un caballo sin nombre
fuente
5

Como otras personas han comentado anteriormente, el uso de TRUNC evitará el uso de índices (si había un índice en TIME_CREATED). Para evitar ese problema, la consulta se puede estructurar como

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 es 1 segundo menos que la cantidad de segundos en un día.

Basanth Roy
fuente