sql >> Databasteknik >  >> RDS >> Oracle

TO_DATE yy, yyyy ger mig olika resultat

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.



  1. ta bort länk tar inte bort någon post i mysql-databasen

  2. sql-fråga - Få skillnadstiden mellan svep in - Svep ut för anställd

  3. bästa sättet att konvertera och validera en datumsträng

  4. I Redshift/Postgres, hur räknar man rader som uppfyller ett villkor?