Desejo armazenar os horários em uma tabela de banco de dados, mas só preciso armazenar as horas e os minutos. Sei que poderia usar DATETIME e ignorar os outros componentes da data, mas qual é a melhor maneira de fazer isso sem armazenar mais informações do que realmente preciso?
sql-server
database
database-design
datetime
Matthew Dresser
fonte
fonte
Respostas:
Você pode armazená-lo como um número inteiro do número de minutos após a meia-noite:
por exemplo.
No entanto, você precisaria escrever algum código para reconstituir o tempo, mas isso não deve ser complicado.
fonte
Se você estiver usando o SQL Server 2008+, considere o
TIME
tipo de dados. Artigo SQLTeam com mais exemplos de uso.fonte
Eu imploro que você use dois valores DATETIME em vez disso, rotulados como algo como event_start e event_end .
O tempo é um negócio complexo
A maior parte do mundo já adotou o sistema métrico baseado em denery para a maioria das medições, correta ou incorretamente. Isso é bom no geral, porque pelo menos todos podemos concordar que ag, é um ml, é um cm cúbico. Pelo menos aproximadamente isso. O sistema métrico tem muitas falhas, mas pelo menos é internacionalmente falho e consistente.
Com o tempo, porém, temos; 1000 milissegundos em um segundo, 60 segundos a um minuto, 60 minutos a uma hora, 12 horas para cada meio dia, aproximadamente 30 dias por mês que variam de acordo com o mês e até mesmo o ano em questão, cada país tem seu tempo deslocado dos outros , a forma como a hora é formatada varia em cada país.
É muito para digerir, mas é impossível para um cenário tão complexo ter uma solução simples.
Alguns cantos podem ser cortados, mas há aqueles em que é mais sensato não
Embora a primeira resposta aqui sugira que armazenar um número inteiro de minutos após a meia-noite possa parecer perfeitamente razoável, aprendi a evitar fazer isso da maneira mais difícil.
As razões para implementar dois valores DATETIME são para um aumento na precisão, resolução e feedback.
Tudo isso é muito útil para quando o design produz resultados indesejáveis.
Estou armazenando mais dados do que o necessário?
Pode parecer que há mais informações sendo armazenadas do que eu preciso, mas há um bom motivo para aceitar isso.
Armazenar essas informações extras quase sempre acaba me economizando tempo e esforço a longo prazo, porque inevitavelmente descubro que quando alguém é informado de quanto tempo algo demorou, ele também vai querer saber quando e onde o evento aconteceu.
É um planeta enorme
No passado, fui culpado de ignorar que existem outros países neste planeta além do meu. Parecia uma boa ideia na época, mas SEMPRE resultou em problemas, dores de cabeça e perda de tempo posteriormente. SEMPRE considere todos os fusos horários.
C #
Um DateTime é renderizado perfeitamente para uma string em C #. O método ToString (string Format) é compacto e fácil de ler.
Por exemplo
Servidor SQL
Além disso, se você estiver lendo seu banco de dados separado da interface do aplicativo, é agradável ler o dateTimes de relance e realizar cálculos neles é simples.
Por exemplo
ISO8601 data padrão
Se estiver usando SQLite, você não tem isso, então use um campo Texto e armazene-o no formato ISO8601, por exemplo.
"2013-01-27T12: 30: 00 + 0000"
Notas:
Este usa relógio de 24 horas *
A parte do deslocamento de tempo (ou +0000) do ISO8601 mapeia diretamente para o valor da longitude de uma coordenada GPS (não levando em consideração o horário de verão ou o país).
Por exemplo
... onde ± se refere à direção leste ou oeste.
Portanto, vale a pena considerar se valeria a pena armazenar longitude, latitude e altitude junto com os dados. Isso vai variar na aplicação.
ISO8601 é um formato internacional.
O wiki é muito bom para mais detalhes em http://en.wikipedia.org/wiki/ISO_8601 .
A data e a hora são armazenadas na hora internacional e o deslocamento é registrado dependendo de onde no mundo a hora foi armazenada.
Na minha experiência, sempre há a necessidade de armazenar a data e a hora completas, independentemente de eu achar que há quando eu começo o projeto. ISO8601 é uma maneira muito boa e à prova de futuro de fazer isso.
Conselhos adicionais grátis
Também vale a pena agrupar eventos como uma cadeia. Por exemplo, se registrar uma corrida, todo o evento pode ser agrupado por piloto, corrida_circuito, pontos de verificação de circuito e voltas_circuito.
Na minha experiência, também é aconselhável identificar quem armazenou o registro. Como uma tabela separada preenchida por meio do gatilho ou como uma coluna adicional na tabela original.
Quanto mais você investe, mais você ganha
Eu entendo perfeitamente o desejo de ser o mais econômico possível com espaço, mas raramente o faria à custa de perder informações.
Uma regra prática com bancos de dados é, como o título diz, um banco de dados só pode dizer o quanto tem dados para, e pode ser muito caro voltar aos dados históricos, preenchendo lacunas.
A solução é acertar na primeira vez. Certamente é mais fácil falar do que fazer, mas agora você deve ter uma visão mais profunda do design de banco de dados eficaz e, subsequentemente, ter uma chance muito maior de acertar da primeira vez.
Quanto melhor for o seu projeto inicial, menos custosos serão os reparos mais tarde.
Só digo isso porque, se pudesse voltar no tempo, é o que diria a mim mesmo quando chegasse lá.
fonte
Basta armazenar uma data e hora regular e ignorar todo o resto. Por que gastar mais tempo escrevendo código que carregue um int, o manipule e o converta em um datetime, quando você poderia simplesmente carregar um datetime?
fonte
DATETIME
tipo de dados leva 4 bytes para armazenar, enquanto um,SMALLINT
por exemplo, leva apenas um quarto disso. Não há grande diferença se você tiver apenas alguns milhares de linhas, mas se tiver muitos milhões de linhas como muitas empresas, sua economia de espaço será substancial.já que você não mencionou nada se estiver no SQL Server 2008, você pode usar o tipo de dados de hora, caso contrário use minutos desde a meia-noite
fonte
Na verdade, o SQL Server armazena o tempo em frações de um dia. Por exemplo, 1 dia inteiro = valor de 1. 12 horas é um valor de 0,5.
Se você deseja armazenar o valor da hora sem utilizar um tipo DATETIME, armazenar a hora na forma decimal seria adequado para essa necessidade, ao mesmo tempo que torna a conversão para DATETIME simples.
Por exemplo:
Armazenar o valor como DECIMAL (9,9) consumiria 5 bytes. No entanto, se a precisão não for de extrema importância, um REAL consumirá apenas 4 bytes. Em ambos os casos, o cálculo agregado (isto é, tempo médio) pode ser facilmente calculado em valores numéricos, mas não em tipos de dados / tempo.
fonte
Gostaria de convertê-los em um número inteiro (HH * 3600 + MM * 60) e armazená-lo dessa forma. Tamanho de armazenamento pequeno e ainda fácil de trabalhar.
fonte
Se você estiver usando o MySQL, use um tipo de campo TIME e a funcionalidade associada que vem com TIME.
00:00:00 é o formato de hora unix padrão.
Se você tiver que olhar para trás e revisar as tabelas manualmente, os números inteiros podem ser mais confusos do que um registro de data e hora real.
fonte
Experimente smalldatetime. Pode não dar o que você deseja, mas irá ajudá-lo em suas necessidades futuras de manipulação de data / hora.
fonte
Tem certeza de que precisará apenas das horas e minutos? Se você quiser fazer algo significativo com ele (como, por exemplo, computar intervalos de tempo entre dois desses pontos de dados), não ter informações sobre fusos horários e DST pode dar resultados incorretos. Os fusos horários talvez não se apliquem ao seu caso, mas o DST certamente se aplicará.
fonte
Em vez de minutos após a meia-noite, nós o armazenamos como relógio de 24 horas, como um SMALLINT.
09:12 = 912 14:15 = 1415
ao converter de volta para a "forma legível por humanos", apenas inserimos dois pontos ":" dois caracteres da direita. Preencher com zeros à esquerda, se necessário. Salva a matemática de cada maneira e usa alguns bytes a menos (em comparação com varchar), além de garantir que o valor seja numérico (em vez de alfanumérico)
Muito idiota ... deveria ter havido um tipo de dados TIME no MS SQL por muitos anos já IMHO ...
fonte
O que acho que você está pedindo é uma variável que armazenará os minutos como um número. Isso pode ser feito com os vários tipos de variável inteira:
Em seguida, em seu programa, você pode simplesmente ver isso na forma que desejar, calculando:
Surge um problema quando você solicita o uso de eficiência. Mas, se você tiver pouco tempo, então use um BigInt anulável para armazenar o valor dos minutos.
Um valor nulo significa que a hora ainda não foi registrada.
Agora, vou explicar na forma de uma viagem de ida e volta ao espaço sideral.
Infelizmente, uma coluna da tabela armazenará apenas um único tipo. Portanto, você precisará criar uma nova tabela para cada tipo, conforme necessário.
Por exemplo:
Se MinutesInput = 0 .. 255 , use TinyInt (converter conforme descrito acima).
Se MinutesInput = 256 .. 131071 então use SmallInt (Observação: o valor mínimo de SmallInt é -32.768. Portanto, negue e adicione 32768 ao armazenar e recuperar o valor para utilizar a faixa completa antes de converter como acima).
Se MinutesInput = 131072 .. 8589934591 , use Int (Observação: negue e adicione 2147483648 conforme necessário).
Se MinutesInput = 8589934592 .. 36893488147419103231 então use BigInt (Observação: adicione e negue 9223372036854775808 conforme necessário).
Se MinutesInput> 36893488147419103231 então eu pessoalmente usaria VARCHAR (X) aumentando X conforme necessário, pois um caractere é um byte. Terei que revisitar essa resposta posteriormente para descrever isso por completo (ou talvez um colega stackoverflowee possa terminar esta resposta).
Como cada valor sem dúvida exigirá uma chave exclusiva, a eficiência do banco de dados só será aparente se a faixa dos valores armazenados for uma boa combinação entre muito pequeno (perto de 0 minutos) e muito alto (maior que 8589934591).
Até que os valores sendo armazenados realmente alcancem um número maior que 36893488147419103231, você também pode ter uma única coluna BigInt para representar seus minutos, já que não será necessário desperdiçar um Int em um identificador exclusivo e outro int para armazenar o valor dos minutos.
fonte
A economia de tempo no formato UTC pode ajudar melhor, como sugeriu Kristen.
Certifique-se de que está usando o relógio de 24 horas porque não há nenhum meridiano AM ou PM para ser usado no UTC.
Exemplo:
Ainda é preferível usar o formato padrão de quatro dígitos.
fonte
Armazene
ticks
comolong
/bigint
, que atualmente são medidos em milissegundos. O valor atualizado pode ser encontrado examinando oTimeSpan.TicksPerSecond
valor.A maioria dos bancos de dados tem um tipo DateTime que armazena automaticamente a hora como ticks nos bastidores, mas no caso de alguns bancos de dados, por exemplo, SqlLite, armazenar ticks pode ser uma forma de armazenar a data.
A maioria dos idiomas permite a conversão fácil de
Ticks
→TimeSpan
→Ticks
.Exemplo
Em C #, o código seria:
Esteja ciente, porém, porque no caso do SqlLite, que oferece apenas um pequeno número de tipos diferentes, que são;
INT
,REAL
eVARCHAR
Será necessário armazenar o número de carrapatos como uma string ou duasINT
células combinadas. Isso ocorre porque umINT
é um número assinado de 32 bits, enquantoBIGINT
um número assinado de 64 bits.Nota
Minha preferência pessoal, entretanto, seria armazenar a data e a hora como uma
ISO8601
string.fonte
IMHO, qual é a melhor solução depende, até certo ponto, de como você armazena o tempo no resto do banco de dados (e no resto do seu aplicativo)
Pessoalmente, tenho trabalhado com SQLite e tento sempre usar carimbos de data / hora unix de / para armazenar o tempo absoluto, então, ao lidar com a hora do dia (como você pediu), faço o que Glen Solsberry escreve em sua resposta e armazeno o número de segundos desde a meia-noite
Ao adotar essa abordagem geral, as pessoas (inclusive eu!) Lendo o código ficam menos confusas se eu usar o mesmo padrão em todos os lugares
fonte