Weil Sie eine unnötige explizite Konvertierung von Zeichenfolge zu Datum durchführen, was eine implizite ausführt Umwandlung von Datum in Zeichenfolge basierend auf Ihren NLS-Einstellungen.
Was Sie tun sollten, ist nur:
select to_char(sysdate - 7, 'year') from dual;
TO_CHAR(SYSDATE-7,'YEAR')
------------------------------------------
twenty seventeen
Weil sysdate-7
bereits ein Datum ist, sollten Sie to_date()
nicht aufrufen darum herum, mit jedem Format. Als to_date()
Die Funktion nimmt ein String-Argument, Ihr sysdate-7
expression muss zuerst implizit in einen String konvertiert werden. Sie tun also wirklich:
select to_char(to_date(to_char(sysdate - 7), 'DD/MM/YYYY'), 'year') from dual;
die Ihren NLS_DATE_FORMAT-Wert für das implizite innere to_char()
verwendet Anruf, also wenn das heißt 'DD-MON-RR'
Sie tun eigentlich:
select to_char(to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YYYY'), 'year') from dual;
Um zu sehen, was dort vor sich geht, müssen Sie sehen, was das vollständige generierte Datum ist, also werde ich das NLS_DATE_FORMAT für die Sitzung ändern, um das vollständige Jahr anzuzeigen:
alter session set nls_date_format = 'SYYYY-MM-DD';
select sysdate - 7 as raw_date,
to_char(sysdate - 7, 'DD-MON-RR') as implicit_string,
to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YY') as implcit_yy,
to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YYYY') as implcit_yyyy
from dual;
RAW_DATE IMPLICIT_STRING IMPLCIT_YY IMPLCIT_YYY
----------- ------------------ ----------- -----------
2017-04-30 30-APR-17 2017-04-30 0017-04-30
Beachten Sie die unterschiedlichen Jahre in den letzten beiden Werten. Die Dokumentation enthält einen Abschnitt zum Formatmodellabgleich
. Die Zeichenfolge, die Sie implizit in der Mitte erstellen, hat eine zweistellige Jahreszahl. Wenn Sie die Zeichenfolge '30-APR-17'
konvertieren zurück zu einem Datum mit einem YY
model, nimmt es „hilfreicherweise“ das aktuelle Jahrhundert an, sodass das Datum als 2017 endet. Aber wenn Sie dieselbe Zeichenfolge mit einem YYYY
umwandeln model it denkt, dass Sie den eingegebenen Wert wirklich gemeint haben, und geht daher nicht von einem Jahrhundert aus - und Sie haben 17 überschritten, sodass Sie am Ende das Jahr 17 erhalten. also 0017 und nicht 2017. (Sie hätten auch mit RRRR
die erwartete Antwort bekommen , aber es ist viel besser, sich an YYYY
zu halten und tatsächlich überall 4-stellige Jahreszahlen verwenden - if Sie müssen eigentlich überhaupt einen String verwenden.)
Im Wesentlichen:Verlassen Sie sich nicht auf NLS-Einstellungen oder implizite Konvertierungen von Datumsangaben in Zeichenfolgen oder umgekehrt.
In diesem Fall brauchen Sie keine Conversions, verwenden Sie also die einfachere Anweisung oben in dieser Antwort.