martes, 2 de abril de 2013

Oracle Database, SQL: El curioso caso de Benjamin Button


Como en la película del 2008, El curioso caso de Benjamin Button, no sólo en la pantalla gigante, se pueden recrear escenarios, subrealistas.

He observado con suma "curiosidad" y ahora, estoy detrás de una respuesta al caso, de cómo en Oracle Database 11gR1/R2, así como en la Beta 2, Oracle Database 12c, el error representado más adelante se genera. Es curioso, que este mes, el mes 10 del año 1582, en todos sus días, se comporte de manera incorrecta. Y es que, si cambiamos el mes y utilizamos setiembre en lugar de Octubre, no hay error en la operación matemática de las fechas, según pueden observan a continuación. El resultado es que entre el 15 de setiembre del año 1582 y el 05 de setiembre de ese mismo año, la diferencia son 10 días.

Pero si lo hacemos, para el mes de Octubre, del mismo año, la respuesta que obtenemos es "0" ( Cero ) días.

Si iniciamos cambiando la fecha del 05 hacia atrás, empieza contando en orden numérico. Así el día 15 de Octubre, menos el día 04, da 1 ( Un día ) de diferencia.
El día 15 de Octubre, menos el día 03, da 2 ( Dos días ) de diferencia.

El día 15 de Octubre, menos el día 04, da 3 ( Tres días ) de diferencia.

El día 15 de Octubre, menos el día 05, da 0 ( Cero días ) de diferencia.

Pero que pasa, si corremos la fecha pivote al 16 de Octubre y la otra fecha de referencia a una cualquiera, la que en este momento se me ocurrió fue el 11 de Octubre.?

SQL> select to_date ('10-15-1582','mm-dd-yyyy')- to_date ('10-11-1582','mm-dd-yyyy') from dual
SQL> TO_DATE('10-15-1582','MM-DD-YYYY')-TO_DATE('10-11-1582','MM-DD-YYYY')
---------------------------------------------------------------------
                                                                    0

SQL> select to_date ('10-16-1582','mm-dd-yyyy')- to_date ('10-11-1582','mm-dd-yyyy') from dual

SQL> TO_DATE('10-16-1582','MM-DD-YYYY')-TO_DATE('10-11-1582','MM-DD-YYYY')
---------------------------------------------------------------------
                                                                    1

La respuesta no es menos alentadora y mi confusión es aún mayor.

Ahora bien, Oracle guarda sus fechas en formato JULIANO, pero miren lo que pasa aquí. Si tomo en cuenta una fecha, cuyo año es 0000 el error, es un ERROR. Si la fecha puede estar entre -4713 y +9999 porque motivo, no puede ser 0? Acaso el primer día de la existencia no "EXISTIO".  "Santa teoría del BIG BANG" Batman.

SQL> select to_date('0000-02-02','yyyy-mm-dd') from dual;
select to_date('0000-02-02','yyyy-mm-dd') from dual
               *
ERROR en línea 1:
ORA-01841: el valor (completo) del año debe estar entre -4713 y +9999, y no
debe ser igual a 0

Tarea: Debo averiguar que es lo que sucede. Realmente, este es uno de los casos más subrealistas que he visto en 23 años de trabajar con base de datos Oracle. Me gustaría, si alguién todavia, tiene versiones menores a 10g, versiones 9i, 8i o 7.x, me indicaran que el fenómeno se reproduce.

Respaldo de la nota:

SQL> connect / as sysdba
Conectado.


SQL> select to_date ('09-15-1582','mm-dd-yyyy')- to_date ('09-05-1582','mm-dd-yyyy') from dual

SQL> TO_DATE('09-15-1582','MM-DD-YYYY')-TO_DATE('09-05-1582','MM-DD-YYYY')

---------------------------------------------------------------------
                                                                   10

SQL> select date '1582-10-15'-date'1582-10-04' from dual;

DATE'1582-10-15'-DATE'1582-10-04'

---------------------------------
                                1

SQL> 

  1* select to_date ('1582-10-15','yyyy-mm-dd')- to_date ('1582-10-04','yyyy-mm-dd') from dual
SQL> /

TO_DATE('1582-10-15','YYYY-MM-DD')-TO_DATE('1582-10-04','YYYY-MM-DD')

---------------------------------------------------------------------
                                                                    1

SQL> select to_date ('1582-10-15','yyyy-mm-dd')- to_date ('1582-10-03','yyyy-mm-dd') from dual

SQL> TO_DATE('1582-10-15','YYYY-MM-DD')-TO_DATE('1582-10-03','YYYY-MM-DD')
---------------------------------------------------------------------
                                                                    2

SQL> select to_date ('1582-10-15','yyyy-mm-dd')- to_date ('1582-10-02','yyyy-mm-dd') from dual

SQL> TO_DATE('1582-10-15','YYYY-MM-DD')-TO_DATE('1582-10-02','YYYY-MM-DD')
---------------------------------------------------------------------
                                                                    3

SQL> 

  1* select to_date ('1582-10-15','yyyy-mm-dd')- to_date ('1582-10-05','yyyy-mm-dd') from dual
SQL> TO_DATE('1582-10-15','YYYY-MM-DD')-TO_DATE('1582-10-05','YYYY-MM-DD')
---------------------------------------------------------------------
                                                                    0

SQL> select to_date ('1582-10-15','yyyy-mm-dd')- to_date ('1582-10-06','yyyy-mm-dd') from dual

SQL> TO_DATE('1582-10-15','YYYY-MM-DD')-TO_DATE('1582-10-06','YYYY-MM-DD')
---------------------------------------------------------------------
                                                                    0
SQL> select to_date ('1582-10-15','yyyy-mm-dd')- to_date ('1582-10-05','yyyy-mm-dd') from dual;

TO_DATE('1582-10-15','YYYY-MM-DD')-TO_DATE('1582-10-05','YYYY-MM-DD')

---------------------------------------------------------------------
                                                                    0

SQL> select to_date ('10-15-1582','mm-dd-yyyy')- to_date ('10-05-1582','mm-dd-yyyy') from dual

SQL> TO_DATE('10-15-1582','MM-DD-YYYY')-TO_DATE('10-05-1582','MM-DD-YYYY')
---------------------------------------------------------------------
                                                                    0
SQL>

2 comentarios:

  1. El calendario gregoriano tiene un desfase justo el año 1582 y al mes de octubre le faltan 10 días...

    Pasa del 4 de octubre al 15 de octubre por decisión "papal", supongo que eso afecta a los cálculos que estás haciendo.

    ResponderEliminar
  2. He estado buscando el enlace donde yo lo descubrí ::

    http://www.reddit.com/r/oracle/comments/18lmt2/why_between_to_date15821015yyyymmdd_and_to/

    ResponderEliminar

Te agradezco tus comentarios. Te esperamos de vuelta.

Todos los Sábados a las 8:00PM

Optimismo para una vida Mejor

Optimismo para una vida Mejor
Noticias buenas que comentar