2017-11-22 1 views
0

Diese CASE zeigt mir nur das gleiche Datum '01/01/2999 ', ich muss dieses Datum '01/01/2999' nur bekommen, wenn das Datum weniger ist '01/. 01/1950‘Fall geben Sie mir das gleiche Datum :(

wenn jemand kann mir helfen, ich fühle mich so dankbar

to_char((
    CASE 
    WHEN to_date(RM.REME_FECHA_ENTREGA,'DD/MM/YYYY') <= to_date('01/01/1950','DD/MM/YYYY') 
    THEN 
    to_date('01/01/2999','DD/MM/YYYY') 
    ELSE 
    to_date(RM.REME_FECHA_ENTREGA,'DD/MM/YYYY') 
    END) ,'DD/MM/YYYY') 
    as FechaEntregaRemesa 
+0

Bitte bearbeiten Sie Ihre Frage, um die Definitionsdaten der Tabelle (oder zumindest der Spalte) und die Probendaten und die erwarteten Ergebnisse einzubeziehen. Und Ihre aktuelle NLS_DATE_FORMAT-Einstellung. Ich werde auf einen Ast gehen und vorschlagen, dass es DD-MON-RR ist, oder zumindest etwas mit einer 2-stelligen Jahr-Maske? Welchen Client verwenden Sie, um das auszuführen? –

+1

Nach seinem Namen 'REME_FECHA_ENTREGA' ist ein ** DATUM **. Was soll 'TO_DATE' damit anfangen? Oder speichern Sie Ihre Daten als Zeichenfolgen? –

+0

Wenn sie als Strings - in diesem Format sowieso - gespeichert wurden, würde die Abfrage das gewünschte Ergebnis erhalten, wie es ist. Das Konvertieren nach Datum in den Fallzweigen und dann zurück zu String wäre natürlich immernoch sinnlos. Ich denke, das ist nur ein (ziemlich häufiges) Missverständnis darüber, wie Datumsformatierung funktioniert. –

Antwort

3

Dies liegt daran, dass Sie implizite Datumsumwandlungen durchführen, und Ihr NLS_DATE_FORMAT hat ein zweistelliges Jahr, z. 'DD/MM/YY' oder diese:

alter session set nls_date_format = 'DD-Mon-RR'; 

-- CTE to generate two dummy values 
with RM (REME_FECHA_ENTREGA) as (
    select date '1950-01-01' from dual 
    union all select date '1950-01-02' from dual 
) 
-- your query plus the original date value 
select to_char(RM.REME_FECHA_ENTREGA, 'SYYYY-MM-DD') as REME_FECHA_ENTREG, 
to_char((
    CASE 
    WHEN to_date(RM.REME_FECHA_ENTREGA,'DD/MM/YYYY') <= to_date('01/01/1950','DD/MM/YYYY') 
    THEN 
    to_date('01/01/2999','DD/MM/YYYY') 
    ELSE 
    to_date(RM.REME_FECHA_ENTREGA,'DD/MM/YYYY') 
    END) ,'DD/MM/YYYY') 
    as FechaEntregaRemesa 
from rm; 

REME_FECHA_ FECHAENTRE 
----------- ---------- 
1950-01-01 01/01/2999 
1950-01-02 01/01/2999 

Mit einem 4-stelligen Format funktioniert es wie erwartet:

alter session set nls_date_format = 'DD/MM/YYYY'; 

... 

REME_FECHA_ FECHAENTRE 
----------- ---------- 
1950-01-01 01/01/2099 
1950-01-02 02/01/1950 

Wenn Sie das tun

to_date(RM.REME_FECHA_ENTREGA,'DD/MM/YYYY') 

Sie eigentlich wirklich tun:

to_date(to_char(RM.REME_FECHA_ENTREGA, '<NLS_DATE_FORMAT>'),'DD/MM/YYYY') 

weshalb yo Sie sehen das Problem mit einem zweistelligen Jahresmodell. Die implizite to_char(RM.REME_FECHA_ENTREGA, 'DD-MON-RR') gibt eine Zeichenfolge wie '01-JAN-50'. Wenn Sie diese Zeichenfolge wieder in to_date() mit einem YYYY Format Modell übergeben Sie es als Jahr 0050 interpretiert hat, so es wird immer vor 1950

"Oracle Database converts strings to dates with some flexibility", die nicht immer hilfreich ist ... hier ist es nicht beschweren, dass Sie habe für ein 4-stelliges Modell zwei Ziffern angegeben oder in meinem Beispiel eine Monatsabkürzung anstelle einer Monatszahl. (Sie können das Verhalten mit den FM/FX-Modifikatoren ändern, aber es ist standardmäßig flexibel.)

Sie könnten versucht sein, alter session zu verwenden, wie ich für diese Demo getan habe, aber sollte nicht auf NLS-Einstellungen verlassen, wie Sie normalerweise haben keine Kontrolle über die Einstellungen anderer Benutzer. (Ich vermute, Sie wussten nicht, dass Sie in dieser Abfrage waren, aber es ist immer noch etwas, worauf Sie achten sollten.) Verwenden Sie immer explizite Konvertierungen und Vollformat-Modelle, wenn Sie Datumsangaben in Zeichenfolgen und umgekehrt konvertieren müssen.

Sie müssen jedoch Ihren vorhandenen Datumswert überhaupt nicht konvertieren. Es ist ein Date, also lass es in Ruhe.Sie können auch Datumsliterale für die festen Werte verwenden, um Unklarheiten zu vermeiden und für ein bisschen weniger tippen:

to_char(
    CASE 
    WHEN RM.REME_FECHA_ENTREGA <= date '1950-01-01' 
    THEN 
    date '2099-01-01' 
    ELSE 
    RM.REME_FECHA_ENTREGA 
    END,'DD/MM/YYYY') 
    as FechaEntregaRemesa 

... 

REME_FECHA_ FECHAENTRE 
----------- ---------- 
1950-01-01 01/01/2099 
1950-01-02 02/01/1950 

oder sogar (@ expenguin Vorschlag zu ändern) nur Daten verwenden, wenn Sie müssen:

CASE 
    WHEN RM.REME_FECHA_ENTREGA <= date '1950-01-01' 
    THEN 
    '01/01/2099' 
    ELSE 
    TO_CHAR(RM.REME_FECHA_ENTREGA, 'DD/MM/YYYY') 
    END as FechaEntregaRemesa 
2

EDIT: so sieht es aus wie Sie nicht einmal die to_char benötigen, wenn Ihre Daten bereits als Text gespeichert wird, und Sie sollten es nicht für den Vergleich benötigen, sondern nur in ein Datum umwandeln, das Sie zum Vergleichen des String-Literals benötigen sollten

so nehmen wir OPs Code:

to_char((
    CASE 
    WHEN to_date(RM.REME_FECHA_ENTREGA,'DD/MM/YYYY') <= to_date('01/01/1950','DD/MM/YYYY') 
    THEN 
    to_date('01/01/2999','DD/MM/YYYY') 
    ELSE 
    to_date(RM.REME_FECHA_ENTREGA,'DD/MM/YYYY') 
    END) ,'DD/MM/YYYY') 
    as FechaEntregaRemesa 

Und unter

ändern, wenn REME_FECHA_ENTREGA ein Datum ist:

CASE 
    WHEN RM.REME_FECHA_ENTREGA <= date '1950-01-01' 
    THEN 
    '01/01/2099' 
    ELSE 
    to_char(RM.REME_FECHA_ENTREGA, 'MM/DD/YYYY') 
    END as FechaEntregaRemesa 

IF REME_FECHA_ENTREGA Ein String ist:

CASE 
    WHEN to_date(RM.REME_FECHA_ENTREGA, 'DD/MM/YYYY') <= date '01/01/1950' 
    THEN 
    '01/01/2999' 
    ELSE 
    RM.REME_FECHA_ENTREGA 
    END as FechaEntregaRemesa 
+0

Doing 'to_char ('01/01/2999 ',' DD/MM/YYYY ')' wird "ORA-01722: ungültige Nummer" werfen. Sie können das String-Literal aber auch direkt verwenden, warum haben Sie überhaupt 'to_char()'? Wenn dies ein NLS-Problem ist, ändert dies jedoch nicht das Ergebnis. Und warum haben Sie illegale einfache Anführungszeichen um den Spaltenausdrucksalias hinzugefügt? Wenn Sie einen Bezeichner in Anführungszeichen haben möchten (und Sie wahrscheinlich nicht), dann brauchen Sie doppelte Anführungszeichen. –

+0

Aktualisiert, aber ich wollte nur helfen. Mein Hintergrund ist in MySQL, das war mein Fehler. Sieht so aus, als ob deine Antwort die richtige ist. – expenguin

+0

Ich schein dich verwirrt zu haben, sorry; zumindest wenn der Spaltendatentyp DATE ist, was ich ziemlich sicher bin. (Der OP-Code würde funktionieren, wenn es ein String wäre.) Bei einem Datum brauchen Sie immer noch den 'to_char (RM.REME_FECHA_ENTREGA, ...)' Teil, oder er wird mit dem Client-Standard formatiert. Ich habe mich nur auf das ''01/01/2099''-Literal bezogen - * das * braucht das' to_char() 'nicht. –

Verwandte Themen