我需要在 T-SQL SELECT语句(在SQL Server 2000上)中将SQL Server DATETIME 值转换为FILETIME 。是否有内置函数来执行此操作?如果没有,有人可以帮我弄清楚如何将这个转换例程实现为UDF(或只是简单的Transact-SQL)?这就是我所知道的:
我找到了几个示例,展示了如何将FILETIME值转换为T-SQL DATETIME(虽然我不是100%确定它们是准确的),但是找不到任何有关反向转换的内容。即使是一般的想法(或算法)也会有所帮助。
答案 0 :(得分:3)
好吧,我想我能够自己实现这一点。这是功能:
IF EXISTS
(
SELECT 1
FROM sysobjects
WHERE id = OBJECT_ID('[dbo].[fnDateTimeToFileTime]')
AND type = 'FN'
)
BEGIN
DROP FUNCTION [dbo].[fnDateTimeToFileTime]
END
GO
-- Create function.
CREATE FUNCTION [dbo].[fnDateTimeToFileTime]
(
@DateTime AS DATETIME
)
RETURNS
BIGINT
BEGIN
IF @DateTime IS NULL
RETURN NULL
DECLARE @MsecBetween1601And1970 BIGINT
DECLARE @MsecBetween1970AndDate BIGINT
SET @MsecBetween1601And1970 = 11644473600000
SET @MsecBetween1970AndDate =
DATEDIFF(ss, CAST('1970-01-01 00:00:00' as DATETIME), @DateTime) *
CAST(1000 AS BIGINT)
RETURN (@MsecBetween1601And1970 + @MsecBetween1970AndDate) * CAST(10000 AS BIGINT)
END
GO
IF @@ERROR = 0
GRANT EXECUTE ON [dbo].[fnDateTimeToFileTime] TO Public
GO
它似乎准确到1秒,这对我来说没问题(由于数据溢出,我无法使其更准确)。我使用TimeAndDate web tool来计算日期之间的持续时间。
您怎么看?
答案 1 :(得分:2)
2 SQL Server时代开始 1900-01-01 00:00:00(每个SELECT CAST(0 作为DATETIME)。
不,这是基准日期,日期时间从1753开始
运行此
select cast('17800122' as datetime)
输出
1780-01-22 00:00:00.000
但是这仍然比文件时间少,所以你需要添加...但请记住格里高利和朱利安日历(也是日期时间从1753年开始的原因)
答案 2 :(得分:1)
可接受的答案效果很好,但是在2038年1月19日以上的日期会崩溃。可以使用 如果您使用的是SQL Server 2016或更高版本,请使用DATEDIFF_BIG代替DATEDIFF,或使用以下更正内容
CREATE FUNCTION [dbo].[fnDateTimeToFileTime]
(
@DateTime AS DATETIME
)
RETURNS
BIGINT
BEGIN
IF @DateTime IS NULL
RETURN NULL
DECLARE @MsecBetween1601And1970 BIGINT
DECLARE @MsecBetween1970AndDate BIGINT
DECLARE @MaxNumberDayBeforeOverflowDateDiff int;
SET @MaxNumberDayBeforeOverflowDateDiff = 24855; --SELECT DATEDIFF(day, CAST('1970-01-01 00:00:00' as DATETIME), CAST('2038-01-19 00:00:00' as DATETIME))
DECLARE @nbMaxDaysBetween1970AndDate int;
SET @nbMaxDaysBetween1970AndDate = DATEDIFF(day, CAST('1970-01-01 00:00:00' as DATETIME), @DateTime) / @MaxNumberDayBeforeOverflowDateDiff;
DECLARE @moduloResteDay int
SET @moduloResteDay = DATEDIFF(day, CAST('1970-01-01 00:00:00' as DATETIME), @DateTime) % @MaxNumberDayBeforeOverflowDateDiff;
DECLARE @nbSecondBefore19700101And20380119 bigint = 2147472000;
SET @MsecBetween1601And1970 = 11644473600000;
DECLARE @DateTimeModulo datetime;
SET @DateTimeModulo = DATEADD(day, -@nbMaxDaysBetween1970AndDate * @MaxNumberDayBeforeOverflowDateDiff, @DateTime)
SET @MsecBetween1970AndDate = CAST(CAST(@nbMaxDaysBetween1970AndDate as bigint) * @nbSecondBefore19700101And20380119 +
DATEDIFF(ss, CAST('1970-01-01 00:00:00' as DATETIME), @DateTimeModulo) as bigint)*
CAST(1000 AS BIGINT)
RETURN (@MsecBetween1601And1970 + @MsecBetween1970AndDate) * CAST(10000 AS BIGINT)
END