Oracle DateTime in Where-Klausel?


83

Ich habe SQL so etwas:

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

-> Dies gibt 10 Zeilen zurück und TIME_CREATED = '26 -JAN-2011 '

Wenn ich das mache, bekomme ich keine Zeilen zurück,

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

-> Hat das Größere als rausgenommen

Irgendein Grund warum?


4
Sie sollten sprachabhängige Datumsformate vermeiden. Dies kann auf verschiedenen Systemen zu Problemen führen. Sie sollten 01anstelle von JAN(und natürlich das entsprechende Format) verwenden, um sicherzustellen, dass Ihr Code auf jedem System problemlos ausgeführt wird.
a_horse_with_no_name

Antworten:


147

Ja: TIME_CREATED enthält ein Datum und eine Uhrzeit . Verwenden Sie TRUNC, um die Zeit zu entfernen:

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

UPDATE:
Wie Dave Costa im folgenden Kommentar ausführt, verhindert dies, dass Oracle den Index der Spalte verwendet, TIME_CREATEDfalls vorhanden. Ein alternativer Ansatz ohne dieses Problem ist folgender:

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
Beachten Sie, dass dieser Ansatz die Verwendung eines Index für TIME_CREATED verhindert, sofern einer vorhanden ist.
Dave Costa

Vielen Dank, dass Sie die Lösung veröffentlicht haben. Es war schnell und leicht zu finden. Während ich an anderen DBMS wie Ingres, MS-SQL, MS-Access und DB2 gearbeitet habe, habe ich vor meiner aktuellen Aufgabe nicht mit Oracle gearbeitet.
Jason TEPOORTEN

Warum nicht verwenden BETWEEN TO_DATE('26/JAN/2011','dd/mon/yyyy') AND TO_DATE('26/JAN/2011','dd/mon/yyyy') + 1?
Ajeh

2
@ajeh: Ich mag nicht betweenwegen der Mehrdeutigkeit. Es klingt so, als ob es ausschließlich die Grenzen ist, obwohl es tatsächlich inklusive ist. Deshalb vermeide ich es. Darüber hinaus wäre es in diesem konkreten Beispiel nicht dasselbe.
Daniel Hilgarth

27

Sie können auch Folgendes verwenden, um den TIME-Teil in Ihre Abfrage aufzunehmen:

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

7

Dies liegt daran, dass eine DATESpalte in Oracle auch einen Zeitteil enthält. Das Ergebnis der to_date()Funktion ist ein Datum, auf das die Uhrzeit eingestellt ist, 00:00:00und daher stimmt es wahrscheinlich nicht mit den Zeilen in der Tabelle überein.

Du solltest benutzen:

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

7

Sie könnten auch tun:

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

5

Wie bereits erwähnt, verhindert die Verwendung von TRUNC die Verwendung von Indizes (wenn für TIME_CREATED ein Index vorhanden war). Um dieses Problem zu vermeiden, kann die Abfrage wie folgt strukturiert werden

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 ist 1 Sekunde weniger als die Anzahl der Sekunden an einem Tag.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.