2016-12-12 1 views
1

Ich versuche, einige Daten aus einer Tabelle auswählen, in dem das Format der Daten sind wie folgt:Mit TO_DATE() mit AM/PM Formatierung

14-APR-14 10.35.00.0000000000 AM 
01-NOV-16 02.43.00.0000000000 PM 

Beachten Sie, dass die Daten entweder AM oder PM sein können, aber wenn ich versuche, ein einfach zu tun SELECT aus der Tabelle wie:

SELECT * FROM MyTable 
WHERE TO_DATE(MyDate, 'DD-MON-YYYY HH:MI:SS AM') > '31-DEC-2016 08:00:00 AM'; 

ich den Fehler:

ORA-01855: AM/A.M. or PM/P.M. required 

ich habe versucht, dies zu umgehen Arbeit für einige Zeit, aber ohne Glück. Jede Hilfe hier würde geschätzt werden.

+0

Sie fehlen Sekundenbruchteile im Format-String. Ist das Datum wirklich als String gespeichert? –

+1

In Oracle speichert der DATE-Datentyp keine Bruchteile von Sekunden. Das wird entweder als Zeitstempel oder als String gespeichert (letzteres ist eine sehr schlechte Wahl). Bitte überprüfen Sie den tatsächlichen Datentyp in der Tabelle, nicht was Sie denken. Dann: Das Vergleichen von Daten als Strings ist immer falsch; im String Vergleich, 01-JAN-2015 .... ist vor 20-NOV-2013. – mathguy

+0

Eigentlich sind das natürlich Zeichenketten, keine Zeitstempel - weil sie ZEHN Dezimalstellen hinter dem Komma haben. Das Maximum in Oracle ist 9, daher müssen Sie zuerst mindestens einige Zeichenfolgen bearbeiten, bevor Sie die Funktionen to_timestamp oder to_date anwenden. – mathguy

Antwort

1

Mehrere Probleme.

Ihre Eingaben offensichtlich Strings sind, da sie höchstens 9. Dann zehn Dezimalstellen und Zeitstempel in Oracle haben haben, Strings mit Bruchteilen einer Sekunde nicht auf ein Datum mit to_date umgerechnet werden können - Sie brauchen to_timestamp zu verwenden oder sonst müssen Sie alle Bruchteile entfernen. In der folgenden Lösung entferne ich nur die letzte (die zehnte) Dezimalstelle, da Sie in der Tabelle nicht-null-gebrochene Teile haben können - allerdings nicht in der von Ihnen geposteten Stichprobe.

Dann Ihre Formatmaske hat yyyy aber Ihre Eingaben haben nur zwei Ziffern für das Jahr (was wahrscheinlich bedeutet, 93 Mittel 1993 und nicht 2093, so die richtige Sache wäre zu verwenden rr anstatt yy). Und Sie verwenden : in der Formatmaske, wo Ihre Eingaben .

verwenden Schließlich vergleichen Sie nicht einmal Datumsangaben im String-Format: in String-Vergleiche 01-JAN-2015 ist vor 20-NOV-2013.

Sie wollen wahrscheinlich etwas wie folgt aus:

select mydate 
from (
     select '14-APR-14 10.35.00.0000000000 AM' as mydate from dual 
     union all 
     select '01-NOV-16 02.43.00.0000000000 PM' from dual 
     ) mytable 
where to_timestamp(substr(mydate, 1, 28) || substr(mydate, -3), 'dd-MON-rr hh.mi.ss.ff AM') 
     > to_timestamp('31-DEC-2016 08:00:00 AM', 'dd-MON-yyyy hh:mi:ss AM'); 

Diese Abfrage kompiliert korrekt, und es erzeugt keine Zeilen in der Ausgabe (aus offensichtlichen Gründen).

HINWEIS: In einem Kommentar Sie (das OP) sagen, das Mydate-Feld ist ein Timestamp (6) -Datentyp. Kaum zu glauben (Sie zeigen zehn Dezimalstellen), aber wenn es tatsächlich ein Zeitstempel oder ein Datum ist, dann müssen Sie es nicht innerhalb einer to_timestamp oder to_date Funktion umbrechen, es sollte allein auf der linken Seite der Ungleichung stehen .

2

Von Ihrem Kommentar:

It's actually a timestamp; not a string. Timestamp(6) to be precise

können Sie nur TIMESTAMP literal verwenden:

SELECT * 
FROM MyTable 
WHERE MyDate > TIMESTAMP '2016-12-31 08:00:00';