Dois campos de banco de dados para data e hora - eles devem ser mesclados?

8

Na pergunta a seguir, os nomes de campos e tabelas foram alterados para proteger suas identidades.

Se eu tiver duas colunas no banco de dados:

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)

O componente de data do campo de horário é definido principalmente como 1º de janeiro de 1753 ... mas alguns dados têm 1º de janeiro de 1899 e outros 1 de janeiro de 1900.

Acho que manter o código para consultar e relatar essas colunas causa a mim (e nossa equipe) uma dor de cabeça que pode ser facilmente resolvida com a mesclagem das duas colunas. No entanto, a experiência (e Terry Goodkind ) me ensinou que nada é fácil. Veja abaixo alguns exemplos de por que isso é uma dor de cabeça.

Minha abordagem

Eu estou pensando que a seguinte abordagem terá o efeito desejado de mesclar as duas colunas:

  1. Use o SQL para atualizar os dados, configurando o valor para o campo de data e o valor para o campo de hora com o mesmo valor, que é uma mistura do componente de data do campo de data e o componente de hora do campo de hora
  2. Escreva qualquer novo código apenas usando o campo MONKEY_DATE
  3. Eventualmente, elimine gradualmente o campo MONKEY_TIME e qualquer componente SQL de data / hora (veja exemplos)
  4. Solte MONKEY_TIME

Isso significa que não precisamos imediatamente fazer alterações retrospectivas em todo o sistema ... todo o código existente continuará funcionando ... e podemos começar a fazer as coisas da maneira certa.

O SQL para o número 1 pode 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')

A questão

Minhas perguntas para você são:

  • Esses campos devem ser mesclados?
  • Minha abordagem é razoável para mesclar essas duas colunas?
  • Você acha que seria melhor pular as etapas dois e três?
  • Você tem outros comentários ou sugestões (construtivos)?

Exemplos

Por exemplo, para selecionar todas as datas e horários dos meus macacos e ordená-los por data e hora, preciso fazer algo assim (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

ou este (Oracle - um pouco mais 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

Também frequentemente me vejo selecionando uma coluna de data / hora mesclada (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, quase o tempo todo, queremos saber a data e a hora do macaco.

O SQL acima pode ser facilmente alterado para:

SELECT MONKEY_DATE_TIME FROM MONKEY ORDER BY MONKEY_DATE_TIME

... Se ao menos tivéssemos mesclado colunas.

fundo

Eu herdei um sistema ASP antigo que armazena datas e horas em colunas separadas no banco de dados. Disseram-me que isso ocorre provavelmente porque o aplicativo foi iniciado em uma versão anterior do Access, onde não era possível armazenar data e hora na mesma coluna. Os porquês e os comos não fazem parte dessa pergunta, mas algumas pessoas gostam de saber.

PS

Eu realmente quase publiquei isso no SO.SE, então peço desculpas se obtive o site errado.

oliver-clare
fonte
Comprometa-se a mesclar. Uma vez confirmado - corte!
Oded

Respostas:

15

Um ponto secundário: quando você mesclar as duas colunas, convém fazer a mesclagem em uma nova coluna "MONKEY_DATE_2" em vez de substituir a existente. Isso deixa suas colunas atuais inalteradas e você pode encontrar todo o código que não foi atualizado para trabalhar com a nova estrutura com grep.

mjfgates
fonte
6
+1. Isso é exatamente o que eu sugeriria (com a exceção de chamar a nova coluna MONKEY_DATETIME).
Doc Brown
5
E não esqueça de adicionar gatilhos que atualizem as colunas antigas quando a nova mudar e vice-versa.
Blrfl
mmm sim. Gatilhos. Pelo menos até o machado cai ... :)
mjfgates
7

Sim, acho que eles devem ser mesclados. Normalmente, eu não me incomodaria em separar os campos de data e hora, a menos que haja boas razões para fazê-lo. Os sistemas legados podem ter sido um bom motivo, mas se os dados foram migrados para um sistema que pode lidar com datas e horários combinados, a fusão é uma boa ideia.

Quanto à sua abordagem, parece razoável. Você pode até executar um pequeno projeto de refatoração para corrigir todo o código ao mesmo tempo, para garantir que todas as suas consultas sejam corrigidas juntas para se livrar do campo "Eventualmente eliminar o campo MONKEY_TIME", embora isso possa demorar algum tempo e provavelmente exigirá testes de regressão significativos. O que não deve ser um problema se você planejar com antecedência.

Investigue também se existem sistemas a jusante (como serviços da Web ou sistemas de relatórios externos) criados a partir de diferentes bases de código, mas ainda dependem de valores separados de data e hora. Se tais sistemas existirem, eles também deverão fazer parte deste plano.

FrustratedWithFormsDesigner
fonte
1
+1 para sistemas a jusante. Temos algumas APIs que precisariam ser verificadas ... Hmm, e isso pode afetar sistemas de terceiros que usam as APIs. Vou ter que pensar sobre isso, obrigado.
Oliver-clare
1
Haha Ambas as respostas têm "Quanto ao seu *, parece razoável". Mentes brilhantes pensam igual? : P
Oleksi
Se o sistema legado ainda estiver essencialmente implantado, verifique se o código que faz referência a essas datas está devidamente encapsulado para fazer referência apenas à data ou hora quando apropriado.
Mikebabcock # 23/12
3

Se a data e a hora sempre forem usadas juntas, mescle as colunas e colha os benefícios de menos dores de cabeça.

Pontos a observar:

  • Uso da coluna de tempo para calcular o tempo relativo entre os dias (por exemplo, "selecione os macacos que entraram em bananas em qualquer dia de uma vez dentro de uma hora após o momento em que esse macaco entrou em bananas").
  • Aritmética na coluna da data que não lida com dias fracionários de maneira sadia.
  • Uso da coluna de data como um mecanismo de agrupamento.

Se você tiver consultas particularmente difíceis, crie uma exibição atualizável que emule o comportamento antigo até que você possa corrigi-los.

Blrfl
fonte
2

Eu tive um problema semelhante em um período de trabalho anterior. Dividimos data e hora em duas colunas do banco de dados. Isso nos causou muitas dores de cabeça. > _ <Com isso dito, eu recomendo que você alterne para uma única coluna de data e hora no seu banco de dados. Isso evitará que muitos bugs subam.

Quanto à sua estratégia, parece razoável, mas certifique-se de envolver toda a equipe nessa decisão e refatoração. Você precisa desencorajar ativamente qualquer pessoa a usar o esquema de dados antigo.

Se não houver muitas alterações de código necessárias (e você tiver algum tempo extra!), Considere fazer a alteração de uma só vez e não terá uma etapa "intermediária" na qual você suporta os dois esquemas de dados. No entanto, isso geralmente é improvável, portanto você provavelmente precisará ter algum tipo de plano de migração como o mencionado na etapa 2/3

Oleksi
fonte
1

Se você está implementando gradualmente essa alteração ao longo do tempo (em vez de preparar todas as alterações e depois instalar tudo de uma vez), tenha cuidado para não ler os valores da nova maneira quando ela foi escrita da maneira antiga. Portanto, a transição precisaria ser:

  1. Todos os novos gravam o novo e o antigo (usar uma nova coluna para o novo caminho ajudaria) e lê o antigo. O código existente é modificado para escrever da maneira nova e da maneira antiga.

  2. Quando todo o código estiver gravando nos dois sentidos, converta os dados existentes para que estejam disponíveis nos dois sentidos.

  3. Todo novo código lê a nova maneira (e ainda grava nos dois sentidos). O código existente é modificado para ler a nova maneira.

  4. Quando todo o código estiver lendo a nova maneira, o novo código poderá escrever apenas a nova maneira, e o código existente poderá ser modificado para somente escrever a nova maneira.

  5. Quando todo o código estiver lendo e gravando da nova maneira, e nenhum código referenciar as colunas antigas, eles poderão ser removidos.

A nova maneira (uma coluna com data e hora) parece obviamente melhor para mim; você precisa decidir se é uma melhoria suficiente para passar pelo processo de conversão.

JGWeissman
fonte