Подтвердить что ты не робот

UNIX_TIMESTAMP в SQL Server

Мне нужно создать функцию в SQL Server 2008, которая будет имитировать mysql UNIX_TIMESTAMP().

Спасибо заранее!

4b9b3361

Ответ 1

Попробуйте этот пост: 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

Ответ 2

Если вам не нужны даты до 1970 года или миллисекундная точность, просто выполните:

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

Почти так же просто, как встроенная функция MySQL:

-- MySQL
SELECT UNIX_TIMESTAMP(DateField);

Другие языки (Oracle, PostgreSQL и т.д.): Как получить текущее время эпохи (отметка времени Unix)

Ответ 3

Мне часто нужна временная метка unix с миллисекундной точностью. Следующее даст вам текущий unixtime как FLOAT; оберните на ответы выше, чтобы получить функцию или преобразовать произвольные строки.

Тип данных DATETIME на SQL Server хорош только до 3 мс, поэтому у меня есть разные примеры для SQL Server 2005 и 2008+. К сожалению, нет функции DATEDIFF2, поэтому необходимы различные трюки, чтобы избежать переполнения целых чисел DATEDIFF даже с 2008+. (Я не могу поверить, что они ввели целый новый тип данных DATETIME2, не исправляя это.)

Для обычного старого DATETIME я просто использую неряшливый прилив для float, который возвращает (с плавающей запятой) количество дней с 1900 года.

Теперь я знаю, на данный момент, вы думаете, что о LEAP SECONDS?!?! Ни время Windows, ни unixtime действительно не верят в прыжковые секунды: день всегда составляет 1.00000 дней для SQL Server и 86400 секунд для unixtime. В этой статье в википедии обсуждается, как работает 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 фактически по умолчанию используют 8-байтовые дубликаты на SQL Server и, следовательно, превосходят 32-разрядные INT для многих случаев использования. (Например, они не перевернутся в 2038 году.)

Ответ 4

Некромантия.
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

Ответ 5

При вызове скалярных функций можно использовать следующий синтаксис

Сценарий функции:

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());

Ответ 6

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()