Fordi du laver en unødvendig eksplicit konvertering fra streng til dato, som laver en implicit konvertering fra dato til streng baseret på dine NLS-indstillinger.
Det du skal gøre er bare:
select to_char(sysdate - 7, 'year') from dual;
TO_CHAR(SYSDATE-7,'YEAR')
------------------------------------------
twenty seventeen
Fordi sysdate-7
allerede er en dato, bør du ikke kalde to_date()
omkring det, med ethvert format. Som to_date()
funktion tager et strengargument, din sysdate-7
udtryk skal implicit konverteres til en streng først. Så du gør virkelig:
select to_char(to_date(to_char(sysdate - 7), 'DD/MM/YYYY'), 'year') from dual;
som bruger din NLS_DATE_FORMAT-værdi for den implicitte indre to_char()
opkald, så hvis det er sig 'DD-MON-RR'
du laver faktisk:
select to_char(to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YYYY'), 'year') from dual;
For at se, hvad der foregår derinde, skal du se, hvad den fulde genererede dato er, så derfor vil jeg ændre NLS_DATE_FORMAT for sessionen for at vise hele å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æg mærke til de forskellige årstal i de sidste to værdier. Dokumentationen har et afsnit om matchning af formatmodeller
. Den streng, du implicit opretter i midten, har et 2-cifret årstal. Når du konverterer strengen '30-APR-17'
tilbage til en dato ved hjælp af en YY
model, antager den "hjælpsomt" det nuværende århundrede, så datoen ender som 2017. Men når du konverterer den samme streng ved hjælp af en YYYY
model den tror, at du virkelig mente den værdi, du har givet, og antager derfor ikke et århundrede - og du bestod det 17, så du ender med året 17; det vil sige 0017 og ikke 2017. (Du ville også have fået det svar, du forventede ved at bruge RRRR
, men det er meget bedre at holde sig til YYYY
og faktisk bruge 4-cifrede årstal overalt - hvis du skal faktisk overhovedet bruge en streng.)
Grundlæggende:Stol ikke på NLS-indstillinger eller implicitte konverteringer af datoer til strenge eller omvendt.
I dette tilfælde behøver du ikke nogle konverteringer, så brug den enklere sætning øverst i dette svar.