sql >> Base de Datos >  >> RDS >> Oracle

TO_DATE yy,yyyy me da resultados diferentes

Porque está haciendo una conversión explícita innecesaria de la cadena a la fecha, lo que está haciendo un implícito conversión de fecha a cadena según su configuración de NLS.

Lo que deberías estar haciendo es simplemente:

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

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

Porque sysdate-7 ya es una fecha, no debería llamar a to_date() alrededor de eso, con cualquier formato. Como to_date() función toma un argumento de cadena, su sysdate-7 expresión tiene que convertirse implícitamente en una cadena primero. Así que realmente estás haciendo:

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

que está utilizando su valor NLS_DATE_FORMAT para el to_char() interno implícito llamar, así que si eso es decir 'DD-MON-RR' en realidad estás haciendo:

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

Para ver lo que sucede allí, debe ver cuál es la fecha generada completa, por lo que voy a cambiar NLS_DATE_FORMAT para que la sesión muestre el año completo:

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

Observe los diferentes años en los dos últimos valores. La documentación tiene una sección sobre coincidencia de modelos de formato . La cadena que está creando implícitamente en el medio tiene un año de 2 dígitos. Cuando convierte la cadena '30-APR-17' volver a una fecha usando un YY modelo, 'útilmente' asume el siglo actual, por lo que la fecha termina en 2017. Pero cuando convierte la misma cadena usando un YYYY model piensa que realmente quiso decir el valor que pasó y, por lo tanto, no asume un siglo, y pasó 17, por lo que termina con el año 17; es decir, 0017 y no 2017. (También habría obtenido la respuesta que esperaba usando RRRR , pero es mucho mejor ceñirse a YYYY y en realidad use años de 4 dígitos en todas partes - if en realidad necesitas usar una cadena).

Esencialmente:no confíe en la configuración de NLS o conversiones implícitas de fechas a cadenas o viceversa.

En este caso, no necesita ninguna conversiones, así que use la declaración más simple en la parte superior de esta respuesta.