sql >> Database teknologi >  >> RDS >> Oracle

TO_DATE yy, yyyy giver mig forskellige resultater

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.



  1. MySQL DEGREES() Funktion – Konverter fra radianer til grader

  2. SQL Server-tjektabel partitioneret

  3. beregning af Max Draw Down i SQL

  4. behov for at gruppere poster baseret på matchende tilbageførsler