Qual:
é a maneira recomendada de armazenar data e hora no SQL Server 2008+?
Estou ciente das diferenças de precisão (e provavelmente do espaço de armazenamento), mas ignorando-as por enquanto, existe um documento de práticas recomendadas sobre quando usar o que ou talvez devamos usar datetime2
apenas apenas?
DateTime2
tipo (ou qualquer outro SQL Server Digite para que o assunto) Ver os Contras na minha 7/10/17 Resposta abaixo por isso que eu estou pedindo?.DATETIME2
tem um intervalo de datas de "0001/01/01" a "DATETIME
9999/12/31 ", enquanto o tipo suporta apenas o ano 1753-9999.Além disso, se você precisar,
DATETIME2
pode ser mais preciso em termos de tempo; DATETIME é limitado a 3 1/3 milissegundos, enquantoDATETIME2
pode ser preciso até 100ns.Ambos os tipos são mapeados
System.DateTime
no .NET - não há diferença.Se você tiver a opção, eu recomendaria o uso
DATETIME2
sempre que possível. Não vejo nenhum benefício ao usarDATETIME
(exceto a compatibilidade com versões anteriores) - você terá menos problemas (com datas fora do intervalo e sem problemas).Além disso: se você precisar apenas da data (sem parte da hora), use DATE - é tão bom quanto
DATETIME2
e economiza espaço também! :-) O mesmo vale apenas para o tempo - useTIME
. É para isso que esses tipos existem!fonte
Nullable<DateTime>
é para isso que serve?datetime2 vence na maioria dos aspectos, exceto (aplicativos antigos Compatibilidade)
observe os seguintes pontos
fonte da imagem: Kit de treinamento individual do MCTS (Exame 70-432): Microsoft® SQL Server® 2008 - Implementação e manutenção Capítulo 3: Tabelas -> Lição 1: Criando tabelas -> página 66
fonte
datetime2
é incrível (Winner)datetime2
usar menos espaço de armazenamento do quedatetime
oferecer uma maior variedade e maior precisão?Concordo com @marc_s e @Adam_Poward - DateTime2 é o método preferido para avançar. Possui um intervalo maior de datas, maior precisão e usa armazenamento igual ou menor (dependendo da precisão).
Uma coisa a discussão perdeu, no entanto ...
@Marc_s afirma:
Both types map to System.DateTime in .NET - no difference there
. Isso está correto, no entanto, o inverso não é verdadeiro ... e é importante ao fazer pesquisas no período (por exemplo, "encontre todos os registros modificados em 5/5/2010").A versão do .NET
Datetime
tem alcance e precisão semelhantes aosDateTime2
. Ao mapear um .netDatetime
para o SQL antigo, ocorreDateTime
um arredondamento implícito . O SQL antigoDateTime
tem precisão de 3 milissegundos. Isso significa que11:59:59.997
é o mais próximo possível do final do dia. Qualquer valor superior é arredondado para o dia seguinte.Tente o seguinte:
Evitar esse arredondamento implícito é um motivo significativo para mudar para DateTime2. O arredondamento implícito de datas causa claramente confusão:
fonte
20100505
para5/5/2010
? O formato anterior funcionará com qualquer região do SQL Server. O último irá quebrar:SET LANGUAGE French; SELECT Convert(datetime, '1/7/2015')
oops:2015-07-01 00:00:00.000
Quase todas as respostas e comentários foram pesadas sobre os profissionais e leves sobre os contras. Aqui está uma recapitulação de todos os prós e contras até agora, além de alguns contras cruciais (no # 2 abaixo) que eu já vi mencionados uma vez ou não.
1.1 Mais compatível com ISO (ISO 8601) (embora eu não saiba como isso entra em jogo na prática).
1.2 Mais alcance (1/1/0001 a 31/12/9999 vs. 1/1 / 1753-12 / 31/9999) (embora o intervalo extra, todos anteriores ao ano 1753, provavelmente não seja usado, exceto por ex., em aplicativos históricos, astronômicos, geológicos etc.).
1.3 Corresponde exatamente ao intervalo do tipo do .NET
DateTime
(embora ambos convertam para frente e para trás sem codificação especial se os valores estiverem dentro do intervalo e da precisão do tipo de destino, exceto a Con # 2.1 abaixo, caso contrário, ocorrerá erro / arredondamento).1.4 Mais precisão (100 nanossegundos, também conhecido como 0,000,000,1 seg. Vs. 3,33 milissegundos, também conhecido como 0,003,33 seg.) (Embora a precisão extra provavelmente não seja usada, exceto, por exemplo, em aplicativos de engenharia / científicos).
1.5 Quando configurado para precisão semelhante (como em 1 milissegundo, não "igual" (como em 3,33 milissegundos) como Iman Abidi afirmou)
DateTime
, usa menos espaço (7 x 8 bytes), mas é claro que você perderia o benefício de precisão que é provavelmente um dos dois (o outro sendo o intervalo) mais elogiado, embora prováveis benefícios desnecessários).2.1 Ao passar um Parâmetro para um .NET
SqlCommand
, você deve especificarSystem.Data.SqlDbType.DateTime2
se pode estar passando um valor fora doDateTime
intervalo e / ou precisão do SQL Server , porque o padrão éSystem.Data.SqlDbType.DateTime
.2.2 Não pode ser implicitamente / facilmente convertido em um valor numérico de ponto flutuante (número de dias desde a data e hora mín.) Para fazer o seguinte nas expressões do SQL Server usando valores e operadores numéricos:
2.2.1 adicione ou subtraia o número de dias ou dias parciais. Nota: Usar o
DateAdd
Function como solução alternativa não é trivial quando você precisa considerar várias, se não todas, partes da data e hora.2.2.2 faça a diferença entre duas datas para fins de cálculo da "idade". Nota: Você não pode simplesmente usar a
DateDiff
Função do SQL Server , porque ela não calculaage
como a maioria das pessoas esperaria, pois se as duas datas atravessarem um limite de calendário / relógio das unidades especificadas, mesmo que por uma pequena fração dessa unidade, vai voltar a diferença de que, como uma unidade contra a 0. Por exemplo, oDateDiff
naDay
's de duas vezes data apenas 1 milissegundo além retornará 1 vs 0 (dias), se essas data vezes são em diferentes dias do calendário (por exemplo, “1999-12-31 23: 59: 59.9999999” e “2000-01-01 00: 00: 00.0000000”). A mesma diferença de 1 milissegundo de data e hora, se movida para que não cruzem um dia do calendário, retornará um "DateDiff" emDay
0 (dias).2.2.3 adote as
Avg
datas e horários (em uma Consulta Agregada) simplesmente convertendo para "Flutuar" primeiro e depois novamente paraDateTime
.NOTA: Para converter
DateTime2
para um numérico, é necessário fazer algo como a seguinte fórmula, que ainda assume que seus valores não são inferiores ao ano de 1970 (o que significa que você está perdendo todo o intervalo extra mais outros 217 anos. Nota: você pode não é possível simplesmente ajustar a fórmula para permitir um intervalo extra, pois você pode encontrar problemas de estouro numérico.25567 + (DATEDIFF(SECOND, {d '1970-01-01'}, @Time) + DATEPART(nanosecond, @Time) / 1.0E + 9) / 86400.0
- Fonte: " https://siderite.dev/blog/how-to-translate-t-sql-datetime2-to.html "Obviamente, você também
Cast
podeDateTime
primeiro (e, se necessário, voltar aDateTime2
), mas perderia os benefícios de precisão e alcance (todos anteriores ao ano de 1753)DateTime2
vs.,DateTime
que são os dois maiores e também ao mesmo tempo o 2 provavelmente menos necessário, o que sugere a questão de por que usá-lo quando você perde as conversões implícitas / fáceis para numérico de ponto flutuante (número de dias) para adição / subtração / benefício "idade" (vs.DateDiff
) /Avg
cálculos, que é grande em minha experiência.Aliás, a
Avg
data e hora é (ou pelo menos deveria ser) um caso de uso importante. a) Além de ser usado para obter duração média quando as datas e horários (desde uma data-base comum) são usadas para representar a duração (uma prática comum), b) também é útil obter uma estatística do tipo painel sobre qual a data média- time está na coluna de data e hora de um intervalo / grupo de linhas. c) Uma consulta ad-hoc padrão (ou pelo menos deve ser padrão) para monitorar / solucionar problemas de valores em uma coluna que pode não ser mais válida / mais e / ou talvez precise ser preterida é listar para cada valor a contagem de ocorrências e (se disponível) osMin
,Avg
eMax
selos de data e hora associado a esse valor.fonte
DateTime
), todos relacionados aos efeitos nas consultas e declarações do SQL Server.DateTime2
eu já mencionei (devido à grande chance de estouro)). Ré. "não funciona para a maioria dos tipos de datas": você só precisa trabalhar com um, e a maioria das datas na maioria dos aplicativos provavelmente nunca precisará ser convertida em outro tipo de data durante toda a vida útil (exceto, talvez, como eu também mencionei ,DateTime2
paraDateTime
(por exemplo, fazer "aritmética em datas"; P). Dado isso, não vale a pena toda a codificação extra em consultas de pesquisa programadas, mas também ad-hoc, para usar um tipo de data não-aritmética.DateTime2 causa estragos se você for um desenvolvedor do Access tentando escrever Now () no campo em questão. Acabei de fazer uma migração do Access -> SQL 2008 R2 e colocou todos os campos de data e hora como DateTime2. Anexando um registro com Now () como o valor bombardeado. Tudo bem em 1/1/2012 14:53:04, mas não em 10/01/2012 14:53:04.
Uma vez que o personagem fez a diferença. Espero que ajude alguém.
fonte
Aqui está um exemplo que mostra as diferenças no tamanho do armazenamento (bytes) e na precisão entre smalldatetime, datetime, datetime2 (0) e datetime2 (7):
que retorna
Portanto, se eu quiser armazenar informações no segundo - mas não no milissegundo - eu posso salvar 2 bytes cada se usar datetime2 (0) em vez de datetime ou datetime2 (7).
fonte
embora exista maior precisão com datetime2 , alguns clientes não suportam data , hora ou datetime2 e forçam você a converter em um literal de cadeia de caracteres. Especificamente, a Microsoft menciona problemas de ODBC, OLE DB, JDBC e SqlClient de "nível inferior" com esses tipos de dados e possui um gráfico mostrando como cada um pode mapear o tipo.
Se valorizar compatibilidade acima da precisão, use data e hora
fonte
Pergunta antiga ... Mas quero acrescentar algo que ainda não foi declarado por ninguém aqui ... (Nota: Esta é minha própria observação, portanto, não peça nenhuma referência)
Datetime2 é mais rápido quando usado nos critérios de filtro.
TLDR:
No SQL 2016, eu tinha uma tabela com cem mil linhas e uma coluna de data e hora ENTRY_TIME porque era necessário armazenar o tempo exato em segundos. Ao executar uma consulta complexa com muitas junções e uma subconsulta, quando usei a cláusula where como:
A consulta foi boa inicialmente quando havia centenas de linhas, mas quando o número de linhas aumentou, a consulta começou a fornecer este erro:
Eu removi a cláusula where e, inesperadamente, a consulta foi executada em 1 segundo, embora agora todas as linhas de todas as datas tenham sido buscadas. Eu executo a consulta interna com a cláusula where, e demorou 85 segundos, e sem a cláusula where, levou 0,01 segundos.
Me deparei com muitos threads aqui para esse problema como desempenho de filtragem de data e hora
Otimizei a consulta um pouco. Mas a velocidade real que obtive foi alterando a coluna datetime para datetime2.
Agora, a mesma consulta que atingiu o tempo limite anterior leva menos de um segundo.
Felicidades
fonte
A interpretação das sequências de datas
datetime
e tambémdatetime2
pode ser diferente ao usarDATEFORMAT
configurações que não são dos EUA . Por exemploIsso retorna
2013-05-06
(ou seja, 6 de maio) paradatetime
e2013-06-05
(ou seja, 5 de junho) paradatetime2
. No entanto, comdateformat
definido comomdy
, ambos@d
e@d2
retorno2013-06-05
.O
datetime
comportamento parece estar em desacordo com a documentação do MSDN dosSET DATEFORMAT
quais afirma: Alguns formatos de cadeias de caracteres, por exemplo ISO 8601, são interpretados independentemente da configuração DATEFORMAT . Obviamente não é verdade!Até que fui mordido por isso, sempre pensei que as
yyyy-mm-dd
datas seriam tratadas corretamente, independentemente das configurações de idioma / localidade.fonte
SET LANGUAGE FRENCH; DECLARE @d DATETIME = '20130605'; SELECT @d;
Tente novamente com os traços.De acordo com este artigo , se você deseja ter a mesma precisão do DateTime usando o DateTime2, basta usar o DateTime2 (3). Isso deve fornecer a mesma precisão, ocupar um número a menos de bytes e fornecer um intervalo expandido.
fonte
Eu apenas tropecei em mais uma vantagem
DATETIME2
: evita um bug noadodbapi
módulo Python , que explode se umdatetime
valor de biblioteca padrão for passado, que possui microssegundos diferentes de zero para umaDATETIME
coluna, mas funciona bem se a coluna estiver definida comoDATETIME2
.fonte
O SQL acima não funcionará com um campo DateTime2. Ele retorna e erro "Tipo de operando em conflito: datetime2 é incompatível com int"
Adicionar 1 para o dia seguinte é algo que os desenvolvedores fazem com datas há anos. Agora, a Microsoft tem um super novo campo datetime2 que não pode lidar com essa funcionalidade simples.
"Vamos usar esse novo tipo que é pior que o antigo", acho que não!
fonte
datetime
edatetime2
foram introduzidos no SQL Server 2008. Você também obtémOperand type clash: date is incompatible with int
odate
tipo que existe desde o dia.dateadd(dd, 1, ...)
Porém, todos os três tipos de dados funcionam bem .Eu acho que
DATETIME2
é a melhor maneira de armazenar odate
, porque tem mais eficiência do que oDATETIME
. EmSQL Server 2008
você pode usarDATETIME2
, ele armazena uma data e hora, leva de 6bytes
a 8 para armazenar e tem uma precisão de100 nanoseconds
. Portanto, qualquer pessoa que precise de maior precisão de tempo desejaráDATETIME2
.fonte