Dos campos de base de datos para fecha y hora: ¿deberían fusionarse?


8

En la siguiente pregunta, los nombres de campos y tablas se han cambiado para proteger sus identidades.

Si tengo dos columnas de base de datos:

MONKEY_DATE DATETIME NULL (with data e.g. 2012-05-14 00:00:00.000)
MONKEY_TIME DATETIME NULL (with data e.g. 1753-01-01 16:30:53.025)

El componente de fecha del campo de tiempo se establece principalmente en 1 de enero de 1753 ... pero algunos datos tienen el 1 de enero de 1899 y algunos tienen el 1 de enero de 1900.

Me parece que mantener el código para consultar e informar sobre estas columnas me causa a mí (y a nuestro equipo) un dolor de cabeza que podría resolverse fácilmente fusionando las dos columnas. Sin embargo, la experiencia (y Terry Goodkind ) me ha enseñado que nada es fácil. Vea a continuación algunos ejemplos de por qué esto es un dolor de cabeza.

Mi acercamiento

Estoy pensando que el siguiente enfoque tendrá el efecto deseado de fusionar las dos columnas:

  1. Use SQL para actualizar los datos, estableciendo el valor para el campo de fecha y el valor para el campo de tiempo en el mismo valor, que es una combinación del componente de fecha del campo de fecha y el componente de tiempo del campo de tiempo
  2. Escriba cualquier código nuevo solo usando el campo MONKEY_DATE
  3. Finalmente, elimine gradualmente el campo MONKEY_TIME y cualquiera de los componentes SQL de fecha / hora (ver ejemplos)
  4. Soltar MONKEY_TIME

Esto significa que no tenemos que realizar cambios retrospectivos en todo el sistema de inmediato ... todo el código existente continuará funcionando ... y podemos comenzar a hacer las cosas de la manera correcta.

SQL para # 1 podría ser (Oracle):

UPDATE MONKEY SET 
    MONKEY_DATE = TO_DATE(TO_CHAR(MONKEY_DATE, 'MM/DD/YYYY ') || 
                      TO_CHAR(MONKEY_TIME, 'HH24:MI:SS'), 
                      'MM/DD/YYYY HH24:MI:SS')
    MONKEY_TIME = TO_DATE(TO_CHAR(MONKEY_DATE, 'MM/DD/YYYY ') || 
                      TO_CHAR(MONKEY_TIME, 'HH24:MI:SS'), 
                      'MM/DD/YYYY HH24:MI:SS')

La pregunta

Mis preguntas para usted son:

  • ¿Deben fusionarse estos campos?
  • ¿Es razonable mi enfoque para fusionar estas dos columnas?
  • ¿Crees que sería mejor omitir los pasos dos y tres?
  • ¿Tiene algún otro comentario (constructivo) o sugerencia?

Ejemplos

Por ejemplo, para seleccionar todas las fechas y horas de mi mono y ordenarlas por fecha y hora, necesito hacer algo como esto (SQL Server):

SELECT 
      CONVERT(DATETIME, CONVERT(VARCHAR, MONKEY_DATE, 101), 101) AS MONKEY_DATE
    , CONVERT(DATETIME, CONVERT(VARCHAR, MONKEY_TIME, 108), 108) AS MONKEY_TIME 
FROM MONKEY 
ORDER BY
      CONVERT(DATETIME, CONVERT(VARCHAR, MONKEY_DATE, 101), 101) DESC
    , CONVERT(DATETIME, CONVERT(VARCHAR, MONKEY_TIME, 108), 108) DESC

o esto (Oracle - un poco más explícito):

SELECT
      TO_DATE(TO_CHAR(MONKEY_DATE, 'MM/DD/YYYY'), 'MM/DD/YYYY') AS MONKEY_DATE
    , TO_DATE(TO_CHAR(MONKEY_TIME, 'HH24:MI:SS'), 'HH24:MI:SS') AS MONKEY_TIME
FROM MONKEY
ORDER BY
      TO_DATE(TO_CHAR(MONKEY_DATE, 'MM/DD/YYYY'), 'MM/DD/YYYY') DESC
    , TO_DATE(TO_CHAR(MONKEY_TIME, 'HH24:MI:SS'), 'HH24:MI:SS') DESC

También a menudo me encuentro seleccionando una columna de fecha / hora fusionada (Oracle):

SELECT 
    TO_DATE(TO_CHAR(MONKEY_DATE, 'MM/DD/YYYY ') || 
            TO_CHAR(MONKEY_TIME, 'HH24:MI:SS'), 
        'MM/DD/YYYY HH24:MI:SS') AS MONKEY_DATE_TIME 
FROM MONKEY

Porque, casi todo el tiempo, queremos saber la fecha y hora del mono.

El SQL anterior podría modificarse fácilmente para:

SELECT MONKEY_DATE_TIME FROM MONKEY ORDER BY MONKEY_DATE_TIME

... Si tan solo hubiéramos fusionado columnas.

Antecedentes

Heredé un antiguo sistema ASP que almacena fechas y horas en columnas separadas en la base de datos. Me han dicho que esto probablemente se deba a que la aplicación comenzó en una versión anterior de Access, donde no era posible almacenar la fecha y la hora en la misma columna. Los porqués y los cómo no son realmente parte de esta pregunta, pero a algunas personas les gusta saber.

PD

Realmente casi publiqué esto en SO.SE, así que mis disculpas si obtuve el sitio equivocado.


Comprometerse a fusionarse. Una vez comprometido, ¡corta!
Oded

Respuestas:


15

Un punto menor: CUANDO combine las dos columnas, es posible que desee fusionarlas en una nueva columna "MONKEY_DATE_2" en lugar de sobrescribir la existente. Eso deja sus columnas actuales sin cambios, y puede encontrar todo el código que no se ha actualizado para trabajar con la nueva estructura con grep.


66
+1. Eso es exactamente lo que iba a sugerir (con la excepción de que llamaría a la nueva columna MONKEY_DATETIME).
Doc Brown

55
Y no olvide agregar activadores que actualicen las columnas antiguas cuando cambie la nueva y viceversa.
Blrfl

mmm si. Disparadores Al menos hasta que caiga el hacha ... :)
mjfgates

7

Sí, creo que deberían fusionarse. Normalmente no me molestaría en separar los campos de fecha y hora a menos que haya una buena razón para hacerlo. Los sistemas heredados podrían haber sido una buena razón, pero si los datos se hubieran migrado a un sistema que pueda manejar fechas y horas combinadas, entonces la fusión es una buena idea.

En cuanto a su enfoque, suena razonable. Es posible que incluso desee ejecutar un pequeño proyecto de refactorización para corregir todo el código al mismo tiempo para asegurarse de que todas sus consultas se corrijan juntas para deshacerse del "Eventualmente eliminar el campo MONKEY_TIME", aunque podría llevar algún tiempo y probablemente requerirá pruebas de regresión significativas. Lo que no debería ser un problema si lo planifica con anticipación.

También investigue si hay sistemas posteriores (como servicios web o sistemas de informes externos) que se crean a partir de diferentes bases de código pero que aún dependen de valores de fecha y hora separados. Si tales sistemas existen, también deberán ser parte de este plan.


1
+1 para sistemas posteriores. Tenemos algunas API que deberían verificarse ... Hmm, y puede afectar a los sistemas de terceros que usan las API. Tendré que pensar en eso, gracias.
Oliver-Clare

1
Jaja. Ambas respuestas tienen "En cuanto a su *, suena razonable". ¿Grandes mentes piensan igual? : P
Oleksi

Si el sistema heredado está esencialmente en su lugar, asegúrese de verificar que el código que hace referencia a esas fechas esté debidamente envuelto para hacer referencia solo a la fecha o solo a la hora cuando sea apropiado.
mikebabcock

3

Si la fecha y la hora siempre se usan juntas, entonces, por supuesto, combine las columnas y aproveche los beneficios de menos dolores de cabeza.

Cosas a tener en cuenta:

  • Uso de la columna de tiempo para calcular el tiempo relativo entre días (p. Ej., "Selección de los monos que se volvieron plátanos en cualquier día a la hora dentro de una hora de cuando este mono se volvió plátano").
  • Aritmética en la columna de fecha que no trata con días fraccionales de una manera sensata.
  • Uso de la columna de fecha como mecanismo de agrupación.

Si tiene consultas existentes que son particularmente difíciles, cree una vista actualizable que emule el comportamiento anterior hasta que pueda corregirlas.


2

Tuve un problema similar en un período de trabajo anterior. Dividimos la fecha y la hora en dos columnas de base de datos. Esto nos causó muchos dolores de cabeza. > _ <Dicho esto, recomiendo encarecidamente que cambie a una sola columna de fecha y hora en su base de datos. Esto evitará la aparición de muchos errores.

En cuanto a su estrategia, parece razonable, pero asegúrese de involucrar a todo el equipo en esta decisión y refactorización. Debe desalentar activamente a cualquier persona para que use el antiguo esquema de datos.

Si no se requieren muchos cambios de código (¡y tiene algo de tiempo extra!), Puede considerar realizar el cambio de una vez y no tener un paso "intermedio" en el que admita ambos esquemas de datos. Sin embargo, esto generalmente es poco probable, por lo que probablemente necesitará tener algún tipo de plan de migración como el que mencionó en el paso 2/3


1

Si está introduciendo este cambio gradualmente con el tiempo (en lugar de preparar todos los cambios y luego instalar todo de una vez), debe tener cuidado de no leer los valores de la manera nueva cuando se escribió de la manera anterior. Entonces la transición tendría que ir:

  1. Todo nuevo escribe tanto la nueva forma como la antigua (sería útil usar una nueva columna para la nueva forma), y lee la forma antigua. El código existente se modifica para escribir tanto la nueva forma como la antigua.

  2. Una vez que todo el código está escribiendo en ambos sentidos, convierta los datos existentes para que estén disponibles en ambos sentidos.

  3. Todo el nuevo código lee la nueva forma (y aún escribe en ambas direcciones). El código existente se modifica para leer la nueva forma.

  4. Una vez que todo el código está leyendo la nueva forma, el nuevo código puede escribir solo la nueva forma, y ​​el código existente puede modificarse para escribir solo la nueva forma.

  5. Una vez que todo el código está leyendo y escribiendo la nueva forma, y ​​ningún código hace referencia a las columnas antiguas, se pueden eliminar.

La nueva forma (una columna con fecha y hora) me parece obviamente mejor, debe decidir si es una mejora suficiente para pasar por el proceso de conversión.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.