SQL Server 中的 UNIX_TIMESTAMP

发布于 2024-12-26 14:09:05 字数 77 浏览 5 评论 0原文

我需要在 SQL Server 2008 中创建一个函数来模仿 mysql 的 UNIX_TIMESTAMP()

I need to create a function in SQL Server 2008 that will mimic mysql's UNIX_TIMESTAMP().

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

三生池水覆流年 2025-01-02 14:09:05

如果您不关心 1970 年之前的日期或毫秒精度,只需执行以下操作:

-- SQL Server
SELECT DATEDIFF(s, '1970-01-01 00:00:00', DateField)

几乎与 MySQL 的内置函数一样简单:

-- MySQL
SELECT UNIX_TIMESTAMP(DateField);

其他语言(Oracle、PostgreSQL 等): 如何获取当前纪元时间...


如果您需要毫秒精度(SQL Server 2016/13.x 及更高版本):

SELECT DATEDIFF_BIG(ms, '1970-01-01 00:00:00', DateField)

If you're not bothered about dates before 1970, or millisecond precision, just do:

-- SQL Server
SELECT DATEDIFF(s, '1970-01-01 00:00:00', DateField)

Almost as simple as MySQL's built-in function:

-- MySQL
SELECT UNIX_TIMESTAMP(DateField);

Other languages (Oracle, PostgreSQL, etc): How to get the current epoch time in ...


If you need millisecond precision (SQL Server 2016/13.x and later):

SELECT DATEDIFF_BIG(ms, '1970-01-01 00:00:00', DateField)
人生百味 2025-01-02 14:09:05

试试这个帖子:
https://web.archive.org/web/20141216081938/http://skinn3r.wordpress.com/2009/01/26/t-sql-datetime-to-unix-timestamp/

CREATE FUNCTION UNIX_TIMESTAMP (
@ctimestamp datetime
)
RETURNS integer
AS 
BEGIN
  /* Function body */
  declare @return integer

  SELECT @return = DATEDIFF(SECOND,{d '1970-01-01'}, @ctimestamp)

  return @return
END

或这篇文章:

http ://mysql.databases.aspfaq.com/how-do-i-convert-a-sql-server-datetime-value-to-a-unix-timestamp.html

代码如下:

CREATE FUNCTION dbo.DTtoUnixTS 
( 
    @dt DATETIME 
) 
RETURNS BIGINT 
AS 
BEGIN 
    DECLARE @diff BIGINT 
    IF @dt >= '20380119' 
    BEGIN 
        SET @diff = CONVERT(BIGINT, DATEDIFF(S, '19700101', '20380119')) 
            + CONVERT(BIGINT, DATEDIFF(S, '20380119', @dt)) 
    END 
    ELSE 
        SET @diff = DATEDIFF(S, '19700101', @dt) 
    RETURN @diff 
END

示例用法:

SELECT dbo.DTtoUnixTS(GETDATE()) 
-- or 
SELECT UnixTimestamp = dbo.DTtoUnixTS(someColumn) 
    FROM someTable

Try this post:
https://web.archive.org/web/20141216081938/http://skinn3r.wordpress.com/2009/01/26/t-sql-datetime-to-unix-timestamp/

CREATE FUNCTION UNIX_TIMESTAMP (
@ctimestamp datetime
)
RETURNS integer
AS 
BEGIN
  /* Function body */
  declare @return integer

  SELECT @return = DATEDIFF(SECOND,{d '1970-01-01'}, @ctimestamp)

  return @return
END

or this post:

http://mysql.databases.aspfaq.com/how-do-i-convert-a-sql-server-datetime-value-to-a-unix-timestamp.html

code is as follows:

CREATE FUNCTION dbo.DTtoUnixTS 
( 
    @dt DATETIME 
) 
RETURNS BIGINT 
AS 
BEGIN 
    DECLARE @diff BIGINT 
    IF @dt >= '20380119' 
    BEGIN 
        SET @diff = CONVERT(BIGINT, DATEDIFF(S, '19700101', '20380119')) 
            + CONVERT(BIGINT, DATEDIFF(S, '20380119', @dt)) 
    END 
    ELSE 
        SET @diff = DATEDIFF(S, '19700101', @dt) 
    RETURN @diff 
END

Sample usage:

SELECT dbo.DTtoUnixTS(GETDATE()) 
-- or 
SELECT UnixTimestamp = dbo.DTtoUnixTS(someColumn) 
    FROM someTable
伴我老 2025-01-02 14:09:05

Sql Server 2016 及更高版本有一个 DATEDIFF_BIG 函数,可用于获取毫秒。

SELECT DATEDIFF_BIG(millisecond, '1970-01-01 00:00:00', GETUTCDATE())

创建一个函数

CREATE FUNCTION UNIX_TIMESTAMP()
    RETURNS BIGINT
AS
BEGIN
    RETURN DATEDIFF_BIG(millisecond, '1970-01-01 00:00:00', GETUTCDATE())
END

并执行它

SELECT dbo.UNIX_TIMESTAMP()

Sql Server 2016 and later have a DATEDIFF_BIG function that can be used to get the milliseconds.

SELECT DATEDIFF_BIG(millisecond, '1970-01-01 00:00:00', GETUTCDATE())

Create a function

CREATE FUNCTION UNIX_TIMESTAMP()
    RETURNS BIGINT
AS
BEGIN
    RETURN DATEDIFF_BIG(millisecond, '1970-01-01 00:00:00', GETUTCDATE())
END

And execute it

SELECT dbo.UNIX_TIMESTAMP()
旧时模样 2025-01-02 14:09:05

对于毫秒结果的时间戳,我从这里找到了这个解决方案 https://gist.github.com/rsim/d11652a8336137832df9

SELECT (cast(DATEDIFF(s, '1970-01-01', GETUTCDATE()) as bigint)*1000+datepart(ms,getutcdate()))

@Rafe 的回答对我来说没有正确工作(MSSQL 20212) - 我有 9 秒的差异。

For timestamp with milliseconds result I found this solution from here https://gist.github.com/rsim/d11652a8336137832df9:

SELECT (cast(DATEDIFF(s, '1970-01-01', GETUTCDATE()) as bigint)*1000+datepart(ms,getutcdate()))

Answer from @Rafe didn't work for me correctly (MSSQL 20212) - I got 9 seconds of difference.

流绪微梦 2025-01-02 14:09:05

我经常需要一个毫秒精度的 unix 时间戳。下面将为您提供当前的unixtime FLOAT;包装上面的答案以获取函数或转换任意字符串。

SQL Server 上的 DATETIME 数据类型仅适用于 3 毫秒,因此我为 SQL Server 2005 和 2008+ 提供了不同的示例。遗憾的是,没有 DATEDIFF2 函数,因此即使在 2008 年以上,也需要各种技巧来避免 DATEDIFF 整数溢出。 (我不敢相信他们在没有修复这个问题的情况下引入了一个全新的 DATETIME2 数据类型。)

对于常规的旧 DATETIME,我只是使用一个低级的强制转换来浮动,它返回 (floating点)自 1900 年以来的天数。

现在我知道此时您在想闰秒怎么样?!?! Windows 时间和 unixtime 都不真正相信闰秒:对于 SQL Server 来说一天总是 1.00000 天长,对于 unixtime 来说一天总是 86400 秒长。 这篇维基百科文章讨论了unixtime在闰秒期间的行为方式;我相信 Windows 只是像任何其他时钟错误一样查看闰秒。因此,虽然当闰秒发生时两个系统之间不存在系统漂移,但它们在闰秒期间和之后的亚秒级别上不会达成一致。

-- the right way, for sql server 2008 and greater
declare @unixepoch2 datetime2;
declare @now2 Datetime2;
declare @days int;
declare @millisec int;
declare @today datetime2;
set @unixepoch2 = '1970-01-01 00:00:00.0000';
set @now2 = SYSUTCDATETIME();
set @days = DATEDIFF(DAY,@unixepoch2,@now2);
set @today = DATEADD(DAY,@days,@unixepoch2);
set @millisec = DATEDIFF(MILLISECOND,@today,@now2);
select (CAST (@days as float) * 86400) + (CAST(@millisec as float ) / 1000)
  as UnixTimeFloatSQL2008

-- Note datetimes are only accurate to 3 msec, so this is less precise 
-- than above, but works on any edition of SQL Server.
declare @sqlepoch datetime;
declare @unixepoch datetime;
declare @offset float;
set @sqlepoch = '1900-01-01 00:00:00';
set @unixepoch = '1970-01-01 00:00:00';
set @offset = cast (@sqlepoch as float) - cast (@unixepoch as float);
select ( cast (GetUTCDate() as float) + @offset) * 86400 
  as UnixTimeFloatSQL2005;

-- Future developers may hate you, but you can put the offset in
-- as a const because it isn't going to change. 
declare @sql_to_unix_epoch_in_days float;
set @sql_to_unix_epoch_in_days = 25567.0;
select ( cast (GetUTCDate() as float) - @sql_to_unix_epoch_in_days) * 86400.0 
  as UnixTimeFloatSQL2005MagicNumber;

FLOAT 实际上在 SQL Server 上默认为 8 字节双精度数,因此在许多用例中优于 32 位INT。 (例如,它们不会在 2038 年滚动。)

I often need a unix timestamp with millisecond precision. The following will give you the current unixtime as FLOAT; wrap per answers above to get a function or convert arbitrary strings.

The DATETIME datatype on SQL Server is only good to 3 msec, so I have different examples for SQL Server 2005 and 2008+. Sadly there is no DATEDIFF2 function, so various tricks are required to avoid DATEDIFF integer overflow even with 2008+. (I can't believe they introduced a whole new DATETIME2 datatype without fixing this.)

For regular old DATETIME, I just use a sleazy cast to float, which returns (floating point) number of days since 1900.

Now I know at this point, you are thinking WHAT ABOUT LEAP SECONDS?!?! Neither Windows time nor unixtime really believe in leap seconds: a day is always 1.00000 days long to SQL Server, and 86400 seconds long to unixtime. This wikipedia article discusses how unixtime behaves during leap seconds; Windows I believe just views leap seconds like any other clock error. So while there is no systematic drift between the two systems when a leap second occurs, they will not agree at the sub-second level during and immediately following a leap second.

-- the right way, for sql server 2008 and greater
declare @unixepoch2 datetime2;
declare @now2 Datetime2;
declare @days int;
declare @millisec int;
declare @today datetime2;
set @unixepoch2 = '1970-01-01 00:00:00.0000';
set @now2 = SYSUTCDATETIME();
set @days = DATEDIFF(DAY,@unixepoch2,@now2);
set @today = DATEADD(DAY,@days,@unixepoch2);
set @millisec = DATEDIFF(MILLISECOND,@today,@now2);
select (CAST (@days as float) * 86400) + (CAST(@millisec as float ) / 1000)
  as UnixTimeFloatSQL2008

-- Note datetimes are only accurate to 3 msec, so this is less precise 
-- than above, but works on any edition of SQL Server.
declare @sqlepoch datetime;
declare @unixepoch datetime;
declare @offset float;
set @sqlepoch = '1900-01-01 00:00:00';
set @unixepoch = '1970-01-01 00:00:00';
set @offset = cast (@sqlepoch as float) - cast (@unixepoch as float);
select ( cast (GetUTCDate() as float) + @offset) * 86400 
  as UnixTimeFloatSQL2005;

-- Future developers may hate you, but you can put the offset in
-- as a const because it isn't going to change. 
declare @sql_to_unix_epoch_in_days float;
set @sql_to_unix_epoch_in_days = 25567.0;
select ( cast (GetUTCDate() as float) - @sql_to_unix_epoch_in_days) * 86400.0 
  as UnixTimeFloatSQL2005MagicNumber;

FLOATs actually default to 8-byte doubles on SQL Server, and therefore superior to 32-bit INT for many use cases. (For example, they won't roll over in 2038.)

春风十里 2025-01-02 14:09:05

死灵术。
ODBC方式:

DECLARE @unix_timestamp varchar(20)
-- SET @unix_timestamp = CAST({fn timestampdiff(SQL_TSI_SECOND,{d '1970-01-01'}, CURRENT_TIMESTAMP)} AS varchar(20)) 

IF CURRENT_TIMESTAMP >= '20380119' 
BEGIN 
    SET @unix_timestamp = CAST
    (
        CAST
        (
            {fn timestampdiff(SQL_TSI_SECOND,{d '1970-01-01'}, {d '2038-01-19'})} 
            AS bigint
        )  
        + 
        CAST
        (
            {fn timestampdiff(SQL_TSI_SECOND,{d '2038-01-19'}, CURRENT_TIMESTAMP)}
            AS bigint
        ) 
    AS varchar(20)
    ) 
END 
ELSE 
    SET @unix_timestamp = CAST({fn timestampdiff(SQL_TSI_SECOND,{d '1970-01-01'}, CURRENT_TIMESTAMP)} AS varchar(20))

PRINT @unix_timestamp

Necromancing.
The ODBC-way:

DECLARE @unix_timestamp varchar(20)
-- SET @unix_timestamp = CAST({fn timestampdiff(SQL_TSI_SECOND,{d '1970-01-01'}, CURRENT_TIMESTAMP)} AS varchar(20)) 

IF CURRENT_TIMESTAMP >= '20380119' 
BEGIN 
    SET @unix_timestamp = CAST
    (
        CAST
        (
            {fn timestampdiff(SQL_TSI_SECOND,{d '1970-01-01'}, {d '2038-01-19'})} 
            AS bigint
        )  
        + 
        CAST
        (
            {fn timestampdiff(SQL_TSI_SECOND,{d '2038-01-19'}, CURRENT_TIMESTAMP)}
            AS bigint
        ) 
    AS varchar(20)
    ) 
END 
ELSE 
    SET @unix_timestamp = CAST({fn timestampdiff(SQL_TSI_SECOND,{d '1970-01-01'}, CURRENT_TIMESTAMP)} AS varchar(20))

PRINT @unix_timestamp
偏闹i 2025-01-02 14:09:05

这是一个不声明任何函数或变量的单行解决方案:

SELECT CAST(CAST(GETUTCDATE()-'1970-01-01' AS decimal(38,10))*86400000.5 as bigint)

Here's a single-line solution without declaring any function or variable:

SELECT CAST(CAST(GETUTCDATE()-'1970-01-01' AS decimal(38,10))*86400000.5 as bigint)
乱了心跳 2025-01-02 14:09:05

如果您必须处理 SQL Server 的早期版本(<2016)并且您只关心正时间戳,我在这里发布了我为非常遥远的日期找到的解决方案(这样您就可以从 @rkosegi 的答案中删除 IF 。

什么)我所做的是首先计算天数差异,然后添加剩余秒数差异。

CREATE FUNCTION [dbo].[UNIX_TIMESTAMP]
( 
    @inputDate DATETIME 
)
RETURNS BIGINT 
AS 
BEGIN
    DECLARE @differenceInDays BIGINT, @result BIGINT;
    SET @differenceInDays = DATEDIFF(DAY, '19700101', @inputDate)
    IF @differenceInDays >= 0
        SET @result = (@differenceInDays * 86400) + DATEDIFF(SECOND, DATEADD(DAY, 0, DATEDIFF(DAY, 0, @inputDate)), @inputDate)
    ELSE
        SET @result = 0
    RETURN @result
END

If you have to deal with previous versions of SQL Server (<2016) and you only care for positive timestamps, I post here the solution I found for very distant dates (so you can get rid of the IF from @rkosegi's answer.

What I did was first calculating the difference in days and then adding the difference in seconds left.

CREATE FUNCTION [dbo].[UNIX_TIMESTAMP]
( 
    @inputDate DATETIME 
)
RETURNS BIGINT 
AS 
BEGIN
    DECLARE @differenceInDays BIGINT, @result BIGINT;
    SET @differenceInDays = DATEDIFF(DAY, '19700101', @inputDate)
    IF @differenceInDays >= 0
        SET @result = (@differenceInDays * 86400) + DATEDIFF(SECOND, DATEADD(DAY, 0, DATEDIFF(DAY, 0, @inputDate)), @inputDate)
    ELSE
        SET @result = 0
    RETURN @result
END
菩提树下叶撕阳。 2025-01-02 14:09:05

当调用标量函数时,可以使用以下语法

函数脚本:

USE [Database]
GO

/****** Object:  UserDefinedFunction [dbo].[UNIX_TIMESTAMP]  ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[UNIX_TIMESTAMP] (
@ctimestamp datetime
)
RETURNS integer
AS
BEGIN
  /* Function body */
  declare @return integer

  SELECT @return = DATEDIFF(SECOND,{d '1970-01-01'}, @ctimestamp)

  return @return
END 
GO

调用函数:

SELECT dbo.UNIX_TIMESTAMP(GETDATE());

When called to Scalar-valued Functions can use following syntax

Function Script :

USE [Database]
GO

/****** Object:  UserDefinedFunction [dbo].[UNIX_TIMESTAMP]  ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[UNIX_TIMESTAMP] (
@ctimestamp datetime
)
RETURNS integer
AS
BEGIN
  /* Function body */
  declare @return integer

  SELECT @return = DATEDIFF(SECOND,{d '1970-01-01'}, @ctimestamp)

  return @return
END 
GO

Call Function :

SELECT dbo.UNIX_TIMESTAMP(GETDATE());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文