Du har måske bemærket, at SQL Server ikke har en ækvivalent til MySQL's UNIX_TIMESTAMP()
funktion.
Det er dog ikke så svært at returnere Unix-tidsstemplet i SQL Server.
Unix-tidsstemplet (også kendt som Unix-epoketid, Unix-tid eller POSIX-tid) er simpelthen det antal sekunder, der er gået siden 00:00:00 torsdag den 1. januar 1970, Coordinated Universal Time (UTC). Derfor kan vi i SQL Server bruge et par T-SQL-funktioner til at returnere dette.
SQL Server Unix-tidsstempel
Sådan kan du returnere Unix-tidsstemplet i SQL Server.
SELECT DATEDIFF(SECOND,'1970-01-01', GETUTCDATE()) AS 'SQL Server Result';
Resultat:
+---------------------+ | SQL Server Result | |---------------------| | 1560833178 | +---------------------+
Så vi kan bruge DATEDIFF()
funktion til at returnere forskellen i sekunder mellem 1970-01-01 og nu. Vi bruger GETUTCDATE()
funktion for at returnere den aktuelle dato og tid i UTC-tid.
Denne kode vil fungere indtil år 2038 ('2038-01-19 03:14:07' for at være præcis). For Unix-tidsstempler efter det, skal du ændre koden lidt. Hvis du har brug for et Unix-tidsstempel efter den dato, så læs videre.
MySQL Unix-tidsstempelækvivalent
Til sammenligning, hvis jeg kører MySQL's UNIX_TIMESTAMP()
på nøjagtig samme tid får jeg dette:
SELECT UNIX_TIMESTAMP() AS 'MySQL Result';
Resultat:
+--------------+ | MySQL Result | +--------------+ | 1560833178 | +--------------+
Samme resultat. MySQL returnerer resultatet som et heltal uden fortegn. Men hvis det (valgfrie) dato-argument sendes, understøtter det det samme interval som TIMESTAMP
datatype.
Tilbagefør millisekunderne
Hvis du har brug for at returnere et Unix-tidsstempel med højere præcision, f.eks. antallet af millisekunder siden ‘1970-01-01 00:00:00.000’ UTC, skal du bytte DATEDIFF()
funktion for DATEDIFF_BIG()
.
Dette er fordi DATEDIFF()
returnerer en int , som er for lille til at håndtere antallet af millisekunder siden 1970. DATEDIFF_BIG()
funktion på den anden side returnerer en bigint med fortegn , hvilket er mere end nok til at håndtere millisekunder.
SELECT DATEDIFF_BIG(MILLISECOND,'1970-01-01 00:00:00.000', SYSUTCDATETIME()) Milliseconds;
Resultat:
+----------------+ | Milliseconds | |----------------| | 1560835305461 | +----------------+
Tilbagefør nanosekunderne
Her er endnu et eksempel, som denne gang går helt op til nanosekunderne siden '1970-01-01 00:00:00.0000000' UTC.
SELECT DATEDIFF_BIG(NANOSECOND,'1970-01-01 00:00:00.0000000', SYSUTCDATETIME()) Nanoseconds;
Resultat:
+---------------------+ | Nanoseconds | |---------------------| | 1560835321500279300 | +---------------------+
Året 2038-problemet
At returnere millisekunder, mikrosekunder og nanosekunder er godt og godt, men strengt taget er det ikke sand Unix Epoch-tid. Unix Epoch-tid er antallet af sekunder siden '1970-01-01 00:00:00'.
Men DATEDIFF_BIG()
kan stadig komme til nytte, når du returnerer streng Unix Epoch-tid. Det kan især hjælpe din database med at overvinde 2038-problemet. I dette tilfælde skal alt efter "2038-01-19 03:14:07" returneres som en bigint (et 8 byte heltal). Dette skyldes, at antallet af sekunder vil være for stort til en int datatype (et 4 byte heltal). int datatypen går kun op til 2.147.483.647, hvorimod en bigt går op til 9.223.372.036.854.775.807.
Derfor skal du bruge DATEDIFF_BIG()
for at returnere Unix-tidsstempler efter '2038-01-19 03:14:07' funktion i stedet for DATEDIFF()
.
For at demonstrere dette er her et eksempel på brug af DATEDIFF()
for at returnere Unix-tid på præcis den dato/tid:
SELECT DATEDIFF(SECOND,'1970-01-01', '2038-01-19 03:14:07') AS 'Unix Epoch time';
Resultat:
+-------------------+ | Unix Epoch time | |-------------------| | 2147483647 | +-------------------+
Så langt så godt. Dette resultat er inden for int interval på -2.147.483.648 til 2.147.483.647 (selvom det er lige ved den øvre grænse), så det korrekte resultat returneres.
Men her er, hvad der sker, hvis vi øger det med et sekund:
SELECT DATEDIFF(SECOND,'1970-01-01', '2038-01-19 03:14:08') AS 'Unix Epoch time';
Resultat:
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.
Vi får fejlen, fordi den returnerede værdi ville være uden for int rækkevidde.
Så som nævnt, alt hvad vi skal gøre er at bytte DATEDIFF()
for DATEDIFF_BIG()
:
SELECT DATEDIFF_BIG(SECOND,'1970-01-01', '2038-01-19 03:14:08') AS 'Unix Epoch time';
Resultat:
+-------------------+ | Unix Epoch time | |-------------------| | 2147483648 | +-------------------+
Dette vil dog ikke nødvendigvis løse alle år 2038-problemer, da de fleste potentielle problemer sandsynligvis vil være afledt af operativsystemet.
Jeg skal også påpege, at ingen af denne kode ikke nødvendigvis vil være immun over for "År 10.000-problemet", fordi det involverer datetime2 datatype, som har et øvre område på '9999-12-31'.