Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como retornar o carimbo de data/hora do Unix no SQL Server (T-SQL)


Você deve ter notado que o SQL Server não possui um equivalente do UNIX_TIMESTAMP() do MySQL função.

No entanto, não é tão difícil retornar o timestamp Unix no SQL Server.

O timestamp Unix (também conhecido como Unix Epoch time, Unix time ou POSIX time) é simplesmente o número de segundos decorridos desde 00:00:00 de quinta-feira, 1 de janeiro de 1970, Coordinated Universal Time (UTC). Portanto, no SQL Server, podemos usar algumas funções T-SQL para retornar isso.


Carimbo de data/hora Unix do SQL Server


Veja como você pode retornar o carimbo de data/hora do Unix no SQL Server.
SELECT DATEDIFF(SECOND,'1970-01-01', GETUTCDATE()) AS 'SQL Server Result';

Resultado:
+---------------------+
| SQL Server Result   |
|---------------------|
| 1560833178          |
+---------------------+

Então podemos usar o DATEDIFF() função para retornar a diferença em segundos entre 1970-01-01 e agora. Usamos o GETUTCDATE() função para retornar a data e hora atuais na hora UTC.

Este código funcionará até o ano de 2038 ('2038-01-19 03:14:07' para ser mais preciso). Para timestamps Unix depois disso, você precisará modificar o código um pouco. Se você precisar de um carimbo de data/hora Unix após essa data, continue lendo.

Equivalente de carimbo de data/hora do MySQL Unix


Para uma comparação, se eu executar o UNIX_TIMESTAMP() do MySQL exatamente ao mesmo tempo, recebo isso:
SELECT UNIX_TIMESTAMP() AS 'MySQL Result';

Resultado:
+--------------+
| MySQL Result |
+--------------+
|   1560833178 |
+--------------+

Mesmo resultado. O MySQL retorna o resultado como um inteiro sem sinal. No entanto, se o argumento de data (opcional) for passado, ele suporta o mesmo intervalo que o TIMESTAMP tipo de dados.

Retorne os milissegundos


Se você precisar retornar um timestamp Unix com maior precisão, digamos, o número de milissegundos desde '1970-01-01 00:00:00.000' UTC, você precisará trocar o DATEDIFF() função para DATEDIFF_BIG() .

Isso ocorre porque DATEDIFF() retorna um int , que é muito pequeno para lidar com o número de milissegundos desde 1970. O DATEDIFF_BIG() por outro lado, retorna um bigint assinado , que é mais do que suficiente para lidar com milissegundos.
SELECT DATEDIFF_BIG(MILLISECOND,'1970-01-01 00:00:00.000', SYSUTCDATETIME()) Milliseconds;

Resultado:
+----------------+
| Milliseconds   |
|----------------|
| 1560835305461  |
+----------------+

Retorne os Nanossegundos


Aqui está outro exemplo, desta vez indo até os nanossegundos desde '1970-01-01 00:00:00.0000000' UTC.
SELECT DATEDIFF_BIG(NANOSECOND,'1970-01-01 00:00:00.0000000', SYSUTCDATETIME()) Nanoseconds;

Resultado:
+---------------------+
| Nanoseconds         |
|---------------------|
| 1560835321500279300 |
+---------------------+

O problema do ano de 2038


Retornar milissegundos, microssegundos e nanossegundos é muito bom, mas estritamente falando, não é o verdadeiro tempo Unix Epoch. O tempo Unix Epoch é o número de segundos desde '1970-01-01 00:00:00'.

No entanto, o DATEDIFF_BIG() ainda pode ser útil ao retornar o tempo estrito do Unix Epoch. Em particular, isso pode ajudar seu banco de dados a superar o problema de 2038. Nesse caso, qualquer coisa após '2038-01-19 03:14:07' precisará ser retornada como bigint (um inteiro de 8 bytes). Isso ocorre porque o número de segundos será muito grande para um int tipo de dados (um inteiro de 4 bytes). O int tipo de dados só vai até 2.147.483.647, enquanto um bigint sobe para 9.223.372.036.854.775.807.

Portanto, para retornar carimbos de data/hora Unix após '2038-01-19 03:14:07', use o DATEDIFF_BIG() função em vez de DATEDIFF() .

Para demonstrar isso, aqui está um exemplo de uso de DATEDIFF() para retornar a hora Unix exatamente nessa data/hora:
SELECT DATEDIFF(SECOND,'1970-01-01', '2038-01-19 03:14:07') AS 'Unix Epoch time';

Resultado:
+-------------------+
| Unix Epoch time   |
|-------------------|
| 2147483647        |
+-------------------+

Até agora tudo bem. Este resultado está dentro do int intervalo de -2.147.483.648 a 2.147.483.647 (embora esteja bem no limite superior) para que o resultado correto seja retornado.

Mas aqui está o que acontece se aumentarmos em um segundo:
SELECT DATEDIFF(SECOND,'1970-01-01', '2038-01-19 03:14:08') AS 'Unix Epoch time';

Resultado:
The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart.

Recebemos o erro porque o valor retornado estaria fora do int alcance.

Então, como mencionado, tudo o que precisamos fazer é trocar DATEDIFF() para DATEDIFF_BIG() :
SELECT DATEDIFF_BIG(SECOND,'1970-01-01', '2038-01-19 03:14:08') AS 'Unix Epoch time';

Resultado:
+-------------------+
| Unix Epoch time   |
|-------------------|
| 2147483648        |
+-------------------+

No entanto, isso não resolverá necessariamente todos os problemas do ano de 2038, pois a maioria dos problemas em potencial provavelmente seria derivada do sistema operacional.

Também devo salientar que nenhum desses códigos não será necessariamente imune ao “Problema do Ano 10.000”, porque envolve o datetime2 tipo de dados, que tem um intervalo superior de '9999-12-31'.