sql >> Databáze >  >> RDS >> Oracle

TO_DATE yy,yyyy mi dává jiné výsledky

Protože provádíte zbytečnou explicitní konverzi z řetězce na datum, což je implicitní převod z data na řetězec na základě vašeho nastavení NLS.

Co byste měli udělat, je jen:

select to_char(sysdate - 7, 'year') from dual;

TO_CHAR(SYSDATE-7,'YEAR')                 
------------------------------------------
twenty seventeen

Protože sysdate-7 je již datum, neměli byste volat to_date() kolem toho v jakémkoli formátu. Jako to_date() funkce přebírá argument řetězce, váš sysdate-7 výraz musí být nejprve implicitně převeden na řetězec. Takže to opravdu děláte:

select to_char(to_date(to_char(sysdate - 7), 'DD/MM/YYYY'), 'year') from dual;

který používá vaši hodnotu NLS_DATE_FORMAT pro implicitní vnitřní to_char() zavolejte, takže pokud to je, řekněte 'DD-MON-RR' vlastně děláte:

select to_char(to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YYYY'), 'year') from dual;

Abyste viděli, co se tam děje, musíte vidět, jaké je úplné vygenerované datum, proto změním NLS_DATE_FORMAT pro relaci tak, aby zobrazoval celý rok:

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

Všimněte si různých let v posledních dvou hodnotách. Dokumentace obsahuje část o porovnávání modelu formátu . Řetězec, který implicitně vytváříte uprostřed, má 2místný rok. Když převedete řetězec '30-APR-17' zpět na datum pomocí YY model, 'užitečně' předpokládá aktuální století, takže datum skončí jako 2017. Ale když převedete stejný řetězec pomocí YYYY model si myslí, že jste skutečně mysleli hodnotu, kterou jste předali, a tak nepředpokládá století - a překročili jste to 17, takže skončíte s rokem 17; tedy 0017 a ne 2017. (Očekávanou odpověď byste také dostali pomocí RRRR , ale mnohem lepší je držet se YYYY a ve skutečnosti všude používejte 4místné roky – pokud ve skutečnosti potřebujete řetězec vůbec použít.)

V zásadě:nespoléhejte na nastavení NLS nebo implicitní převody dat na řetězce nebo naopak.

V tomto případě nepotřebujete žádné konverze, takže použijte jednodušší prohlášení v horní části této odpovědi.



  1. Oracle DBMS - Přečtěte si tabulku před zpracováním Aktualizace ve spouštěči AFTER - mutující tabulka

  2. Příkaz SQL pro zápis tabulky?

  3. Jak duplikovat schémata v PostgreSQL

  4. Hibernace časové razítko s časovým pásmem