AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 51440
Accepted
Martin Smith
Martin Smith
Asked: 2013-10-14 05:44:58 +0800 CST2013-10-14 05:44:58 +0800 CST 2013-10-14 05:44:58 +0800 CST

Como combinar data e hora para datetime2 no SQL Server?

  • 772

Dados os seguintes componentes

DECLARE @D DATE = '2013-10-13'
DECLARE @T TIME(7) = '23:59:59.9999999'

Qual a melhor forma de combiná-los para produzir um DATETIME2(7)resultado com valor '2013-10-13 23:59:59.9999999'?

Algumas coisas que não funcionam estão listadas abaixo.


SELECT @D + @T 

A data do tipo de dados do operando é inválida para o operador add.


SELECT CAST(@D AS DATETIME2(7)) + @T 

O tipo de dados do operando datetime2 é inválido para o operador add.


SELECT DATEADD(NANOSECOND,DATEDIFF(NANOSECOND,CAST('00:00:00.0000000' AS TIME),@T),@D)

A função dateiff resultou em um estouro. O número de partes de data que separam duas instâncias de data/hora é muito grande. Tente usar datediff com um datepart menos preciso.

* O estouro pode ser evitado no Banco de Dados SQL do Azure e no SQL Server 2016, usando DATEDIFF_BIG.


SELECT CAST(@D AS DATETIME) + @T 

Os tipos de dados datetime e time são incompatíveis no operador add.


SELECT CAST(@D AS DATETIME) + CAST(@T AS DATETIME)

Retorna um resultado, mas perde a precisão2013-10-13 23:59:59.997

sql-server datatypes
  • 6 6 respostas
  • 64651 Views

6 respostas

  • Voted
  1. Best Answer
    ypercubeᵀᴹ
    2013-10-14T07:47:47+08:002013-10-14T07:47:47+08:00

    Isso parece funcionar e manter a precisão também:

    SELECT DATEADD(day, DATEDIFF(day,'19000101',@D), CAST(@T AS DATETIME2(7)))
    

    O CASTto DATETIME2(7)converte o TIME(7)valor ( @T) para um DATETIME2onde a parte da data é '1900-01-01', que é o valor padrão dos tipos date e datetime (consulte datetime2e o comentário * em CASTeCONVERT página no MSDN.)

    * ... Quando dados de caracteres que representam apenas componentes de data ou apenas de hora são convertidos para os tipos de dados datetime ou smalldatetime, o componente de hora não especificado é definido como 00:00:00.000 e o componente de data não especificado é definido como 1900-01- 01 .

    A função DATEADD()e DATEDIFF()cuida do resto, ou seja, somando a diferença em dias entre o 1900-01-01e o DATEvalor ( @D).

    Teste em: SQL-Fiddle


    Conforme observado por @Quandary , a expressão acima é considerada não determinística pelo SQL Server. Se queremos uma expressão determinística, digamos porque ela deve ser usada para uma PERSISTEDcoluna, o '19000101'** precisa ser substituído por 0ou CONVERT(DATE, '19000101', 112):

    CREATE TABLE date_time
    ( d DATE NOT NULL,
      t TIME(7) NOT NULL,
      dt AS DATEADD(day, 
                    DATEDIFF(day, CONVERT(DATE, '19000101', 112), d), 
                    CAST(t AS DATETIME2(7))
                   ) PERSISTED
    ) ;
    

    **: DATEDIFF(day, '19000101', d)não é determinístico, pois faz uma conversão implícita da string para DATETIMEe as conversões de strings para datetime são determinísticas somente quando estilos específicos são usados.

    • 54
  2. knuckles
    2017-04-22T02:20:58+08:002017-04-22T02:20:58+08:00

    Estou atrasado para a festa, mas essa abordagem, embora semelhante à resposta do @ypercube , evita a necessidade de usar qualquer conversão de string (que pode ser mais cara que as conversões de data), é determinística e deve continuar a funcionar se a MS alterar o valor de data padrão de 1900-01-01 (mesmo que eles provavelmente não mudem isso):

    DECLARE @D DATE = SYSUTCDATETIME()
    , @T TIME = SYSUTCDATETIME();
    
    SELECT DATEADD(DAY, DATEDIFF(DAY, @T, @D), CONVERT(DATETIME2, @T));
    

    O princípio é que, convertendo o valor de hora para datetime2 e depois para date, ele retira o tempo limite e atribui a data padrão, você datediff isso com o valor de data para obter os dias a serem adicionados, lança seu tempo para datetime2 e adiciona o dias em.

    • 14
  3. Michael Green
    2018-07-16T19:40:50+08:002018-07-16T19:40:50+08:00

    Para SQL Server 2012 e superior, existe a função DATETIME2FROMPARTS . Tem esta forma:

    DATETIME2FROMPARTS(year, month, day, hour, minute, seconds, fractions, precision)
    

    Para os dados de amostra fornecidos, isso se torna

    select Answer = DATETIME2FROMPARTS(2013, 10, 13, 23, 59, 59, 9999999, 7);
    

    o que resulta em

    Answer
    ---------------------------
    2013-10-13 23:59:59.9999999
    

    As partes podem ser obtidas usando DATEPART() se partir de tipos de dados temporais, ou do texto usado para construir os valores de amostra na pergunta.

    • 6
  4. Brian Jorden
    2019-07-30T05:03:49+08:002019-07-30T05:03:49+08:00

    Eu estava procurando outra coisa quando cheguei aqui. A pergunta é bem antiga, mas há alguns comentários e atividades recentes. Pensei em compartilhar um método simples que é muito semelhante à resposta que @Atario deu, mas um pouco mais curto e alguns podem achar mais fácil de ler:

    declare @d date = '2013-10-13'
    declare @t time(7) = '23:59:59.9999999'
    
    select cast(concat(@d, ' ', @t) as datetime2(7))
    
    • 4
  5. Bogdan Sahlean
    2013-10-14T06:52:49+08:002013-10-14T06:52:49+08:00

    Converti os dois valores (@D e @T) para binário, concatenei valores binários e depois outra conversão de volta para DT2(7):

    SET NOCOUNT ON;
    
    DECLARE @D DATE = '2013-10-13'
    DECLARE @T TIME(7) = '23:59:59.9999999'
    DECLARE @DT2 DATETIME2(7) = '2013-10-13T23:59:59.9999999'
    
    SELECT CONVERT(BINARY(6), @T) AS T, CONVERT(BINARY(3), @D) AS D
    SELECT CONVERT(BINARY(9), @DT2) AS DT2
    SELECT CONVERT(BINARY(6), @T) + CONVERT(BINARY(3), @D) AS DT2_BinaryConcat
    
    DECLARE @DT2_AsBinary BINARY(9), @DT2_AsDateTime2 DATETIME2(7);
    SET @DT2_AsBinary = CONVERT(BINARY(6), @T) + CONVERT(BINARY(3), @D);
    SET @DT2_AsDateTime2 = CONVERT(DATETIME2(7), @DT2_AsBinary);
    SELECT @DT2_AsDateTime2 AS DT2_Converted;
    

    Resultados:

    T              D
    -------------- --------
    0x07FFBF692AC9 0xB1370B
    
    DT2
    --------------------
    0x07FFBF692AC9B1370B
    
    DT2_BinaryConcat
    --------------------
    0x07FFBF692AC9B1370B
    
    DT2_Converted
    ----------------------
    2013-10-13 23:59:59.9999999
    

    Ou, de forma mais compacta:

    DECLARE 
        @D date = '2013-10-13',
        @T time(7) = '23:59:59.9999999';
    
    SELECT DT2 =
        CONVERT(datetime2(7), 
            CONVERT(binary(6), @T) + 
            CONVERT(binary(3), @D));
    

    O time(7)valor é convertido em binary(6)vez do tamanho de armazenamento documentado de 5 bytes porque, ao converter para binário, o SQL Server prefixa um byte de precisão para garantir que a conversão de ida e volta seja possível. Isso está documentado em uma nota de rodapé para datetime2mas não time.

    A concatenação simples funciona neste caso porque a timeprecisão é a mesma que a datetime2precisão desejada. Caso contrário, você precisaria remover o byte de precisão e substituí-lo pelo valor necessário.

    Esse método depende de detalhes de implementação que podem ser alterados e, portanto, não é documentado e não tem suporte .

    db<>violino

    • 2
  6. Atario
    2014-06-11T11:32:11+08:002014-06-11T11:32:11+08:00

    É muito estúpido do SQL Server não deixar seu primeiro exemplo funcionar, e isso vai parecer muito idiota também, mas…

    select convert(datetime2, convert(nvarchar(max), @d) + ' ' + convert(nvarchar(max), @t));
    
    • 0

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Conceder acesso a todas as tabelas para um usuário

    • 5 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve