Eftersom du gör en onödig explicit konvertering från sträng till datum, vilket gör en implicit konvertering från datum till sträng baserat på dina NLS-inställningar.
Det du borde göra är bara:
select to_char(sysdate - 7, 'year') from dual;
TO_CHAR(SYSDATE-7,'YEAR')
------------------------------------------
twenty seventeen
Eftersom sysdate-7
redan är ett datum, bör du inte anropa to_date()
runt det, med vilket format som helst. Som to_date()
funktionen tar ett strängargument, din sysdate-7
uttryck måste först implicit konverteras till en sträng. Så du gör verkligen:
select to_char(to_date(to_char(sysdate - 7), 'DD/MM/YYYY'), 'year') from dual;
som använder ditt NLS_DATE_FORMAT-värde för den implicita inre to_char()
ring, så om det är säg 'DD-MON-RR'
du gör faktiskt:
select to_char(to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YYYY'), 'year') from dual;
För att se vad som händer där inne måste du se vad det fullständiga genererade datumet är, så för det kommer jag att ändra NLS_DATE_FORMAT för sessionen för att visa hela året:
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
Lägg märke till de olika åren i de två senaste värdena. Dokumentationen har ett avsnitt om formatmodellmatchning
. Strängen du implicit skapar i mitten har ett tvåsiffrigt årtal. När du konverterar strängen '30-APR-17'
tillbaka till ett datum med en YY
modell, antar den "hjälpsamt" det aktuella århundradet, så datumet slutar som 2017. Men när du konverterar samma sträng med en YYYY
modell den tror att du verkligen menade det värde du skickade in och antar därför inte ett sekel - och du klarade det 17, så du slutar med årtalet 17; det vill säga 0017 och inte 2017. (Du skulle också ha fått svaret du förväntade dig med RRRR
, men det är mycket bättre att hålla sig till YYYY
och använder faktiskt fyrsiffriga årtal överallt - om du behöver faktiskt använda en sträng alls.)
I huvudsak:lita inte på NLS-inställningar eller implicita konverteringar av datum till strängar eller vice versa.
I det här fallet behöver du inte några omvandlingar, så använd det enklare påståendet överst i det här svaret.