Oracle
 sql >> Base de données >  >> RDS >> Oracle

TO_DATE yy,yyyy me donne des résultats différents

Parce que vous faites une conversion explicite inutile de chaîne en date, ce qui fait un implicite conversion de date en chaîne en fonction de vos paramètres NLS.

Ce que vous devriez faire, c'est simplement :

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

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

Parce que sysdate-7 est déjà une date, vous ne devriez pas appeler to_date() autour de cela, avec n'importe quel format. En tant que to_date() la fonction prend un argument de chaîne, votre sysdate-7 expression doit d'abord être implicitement convertie en chaîne. Alors vous faites vraiment :

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

qui utilise votre valeur NLS_DATE_FORMAT pour le to_char() intérieur implicite appeler, donc si c'est dire 'DD-MON-RR' vous êtes en train de faire :

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

Pour voir ce qui se passe là-dedans, vous devez voir quelle est la date complète générée, donc pour cela, je vais changer le NLS_DATE_FORMAT pour que la session affiche l'année complète :

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

Remarquez les différentes années dans les deux dernières valeurs. La documentation comporte une section sur la correspondance des modèles de format . La chaîne que vous créez implicitement au milieu a une année à 2 chiffres. Lorsque vous convertissez la chaîne '30-APR-17' revenir à une date en utilisant un YY modèle, il suppose "utilement" le siècle actuel, donc la date se termine en 2017. Mais lorsque vous convertissez la même chaîne en utilisant un YYYY modèle, il pense que vous vouliez vraiment dire la valeur que vous avez transmise et ne suppose donc pas un siècle - et vous l'avez dépassé 17, donc vous vous retrouvez avec l'année 17 ; c'est-à-dire 0017 et non 2017. (Vous auriez également obtenu la réponse que vous attendiez en utilisant RRRR , mais il vaut mieux s'en tenir à YYYY et utiliser en fait des années à 4 chiffres partout - si vous avez en fait besoin d'utiliser une chaîne.)

Essentiellement :ne vous fiez pas aux paramètres NLS ou aux conversions implicites de dates en chaînes ou vice versa.

Dans ce cas, vous n'avez besoin de aucune conversions, utilisez donc la déclaration la plus simple en haut de cette réponse.