Мне нужно создать функцию в SQL Server 2008, которая будет имитировать mysql UNIX_TIMESTAMP()
.
Спасибо заранее!
Мне нужно создать функцию в SQL Server 2008, которая будет имитировать mysql UNIX_TIMESTAMP()
.
Спасибо заранее!
Попробуйте этот пост: 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
или этот пост:
код выглядит следующим образом:
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
Если вам не нужны даты до 1970 года или миллисекундная точность, просто выполните:
-- SQL Server
SELECT DATEDIFF(s, '1970-01-01 00:00:00', DateField)
Почти так же просто, как встроенная функция MySQL:
-- MySQL
SELECT UNIX_TIMESTAMP(DateField);
Другие языки (Oracle, PostgreSQL и т.д.): Как получить текущее время эпохи (отметка времени Unix)
Мне часто нужна временная метка 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 году.)
Некромантия.
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
При вызове скалярных функций можно использовать следующий синтаксис
Сценарий функции:
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());
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()