sql >> Base de Datos >  >> RDS >> Sqlserver

Cómo devolver la marca de tiempo de Unix en SQL Server (T-SQL)

Es posible que haya notado que SQL Server no tiene un equivalente de UNIX_TIMESTAMP() de MySQL función.

Sin embargo, no es tan difícil devolver la marca de tiempo de Unix en SQL Server.

La marca de tiempo de Unix (también conocida como hora de época de Unix, hora de Unix o hora POSIX) es simplemente la cantidad de segundos que han transcurrido desde las 00:00:00 del jueves 1 de enero de 1970, hora universal coordinada (UTC). Por lo tanto, en SQL Server podemos usar un par de funciones T-SQL para devolver esto.

Marca de tiempo de SQL Server Unix

Así es como puede devolver la marca de tiempo de Unix en SQL Server.

SELECT DATEDIFF(SECOND,'1970-01-01', GETUTCDATE()) AS 'SQL Server Result';

Resultado:

+---------------------+
| SQL Server Result   |
|---------------------|
| 1560833178          |
+---------------------+

Entonces podemos usar DATEDIFF() para devolver la diferencia en segundos entre 1970-01-01 y ahora. Usamos el GETUTCDATE() función para devolver la fecha y hora actual en hora UTC.

Este código funcionará hasta el año 2038 ('2038-01-19 03:14:07' para ser precisos). Para las marcas de tiempo de Unix después de eso, deberá modificar el código ligeramente. Si necesita una marca de tiempo de Unix posterior a esa fecha, siga leyendo.

Equivalente de marca de tiempo MySQL Unix

A modo de comparación, si ejecuto UNIX_TIMESTAMP() de MySQL exactamente al mismo tiempo, obtengo esto:

SELECT UNIX_TIMESTAMP() AS 'MySQL Result';

Resultado:

+--------------+
| MySQL Result |
+--------------+
|   1560833178 |
+--------------+

Mismo resultado. MySQL devuelve el resultado como un entero sin signo. Sin embargo, si se pasa el argumento de fecha (opcional), admite el mismo rango que TIMESTAMP tipo de datos.

Devolver los milisegundos

Si necesita devolver una marca de tiempo de Unix con mayor precisión, por ejemplo, la cantidad de milisegundos desde '1970-01-01 00:00:00.000' UTC, deberá cambiar el DATEDIFF() función para DATEDIFF_BIG() .

Esto se debe a que DATEDIFF() devuelve un int , que es demasiado pequeño para manejar la cantidad de milisegundos desde 1970. El DATEDIFF_BIG() por otro lado, devuelve un bigint firmado , que es más que suficiente para manejar milisegundos.

SELECT DATEDIFF_BIG(MILLISECOND,'1970-01-01 00:00:00.000', SYSUTCDATETIME()) Milliseconds;

Resultado:

+----------------+
| Milliseconds   |
|----------------|
| 1560835305461  |
+----------------+

Devolver los Nanosegundos

Aquí hay otro ejemplo, esta vez yendo hasta los nanosegundos 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 |
+---------------------+

El problema del año 2038

Devolver milisegundos, microsegundos y nanosegundos está muy bien, pero estrictamente hablando, no es el verdadero tiempo de Unix Epoch. El tiempo de Unix Epoch es el número de segundos desde '1970-01-01 00:00:00'.

Sin embargo, el DATEDIFF_BIG() todavía puede ser útil cuando se devuelve el tiempo estricto de Unix Epoch. En particular, podría ayudar a su base de datos a superar el problema de 2038. En este caso, cualquier cosa posterior a '2038-01-19 03:14:07' deberá devolverse como bigint (un entero de 8 bytes). Esto se debe a que la cantidad de segundos será demasiado grande para un int tipo de datos (un entero de 4 bytes). El int el tipo de datos solo sube a 2,147,483,647, mientras que un bigint sube a 9.223.372.036.854.775.807.

Por lo tanto, para devolver las marcas de tiempo de Unix más allá de '2038-01-19 03:14:07', use DATEDIFF_BIG() función en lugar de DATEDIFF() .

Para demostrar esto, aquí hay un ejemplo del uso de DATEDIFF() para devolver la hora de Unix exactamente en esa fecha/hora:

SELECT DATEDIFF(SECOND,'1970-01-01', '2038-01-19 03:14:07') AS 'Unix Epoch time';

Resultado:

+-------------------+
| Unix Epoch time   |
|-------------------|
| 2147483647        |
+-------------------+

Hasta aquí todo bien. Este resultado está dentro del int rango de -2,147,483,648 a 2,147,483,647 (aunque está justo en el límite superior) por lo que se devuelve el resultado correcto.

Pero esto es lo que sucede si lo aumentamos en un 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.

Obtenemos el error porque el valor devuelto estaría fuera del int rango.

Entonces, como se mencionó, todo lo que tenemos que hacer es intercambiar 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        |
+-------------------+

Sin embargo, esto no resolverá necesariamente todos los problemas del año 2038, ya que la mayoría de los problemas potenciales probablemente se deriven del sistema operativo.

También debo señalar que nada de este código será necesariamente inmune al "Problema del año 10,000", porque involucra el datetime2 tipo de datos, que tiene un rango superior de '9999-12-31'.