提问者:小点点

在执行datetime比较时,如何解释datetime缺少毫秒精度?


我最近了解到,SQL Server的datetime类型只存储大约1/300秒的时间。

所以给出这些数据:

create table datetime_test (id int, my_date datetime);
insert into datetime_test (id, my_date) values
    (0, '2020-12-11 17:14:07.000'),
    (1, '2020-12-11 17:14:07.197'),
    (2, '2020-12-11 17:14:07.198'),
    (3, '2020-12-11 17:14:08.000');

该查询将返回(1,2,3),而不是人们可能预期的(2,3):

select id from datetime_test where my_date >= '2020-12-11 17:14:07.198';

原因是此datetime的毫秒部分实际上存储为.197:

-- Result: 2020-12-11 17:14:07.197
select convert(datetime, '2020-12-11 17:14:07.198');

我正在使用现有的C#代码,这些代码使用SQL来使用>=比较日期时间。像这样的东西:

public Foo GetMyColumn(DateTime inputDatetime)
{
  // ...
}
select my_column
from my_table
where my_datetime >= @inputDatetime

我试图重用这个C#方法来执行排他比较。。。相当于使用>。我怎么能那么做?

我最初的尝试是在datetime输入中添加一毫秒(在C#中),但是由于上面概述的精度问题,这将行不通。我想我可以增加3毫秒。感觉像是被黑了。但它能可靠地工作吗?

注意:请假设我无法更改此SQL或方法。


共1个答案

匿名用户

您会发现windows时钟可能不像您所需要的那样精确。此外,您的服务器的时钟不是那么精确,取决于负载它可能是滞后的,出于这个原因,我们使用特殊的硬件与GPS定时器时,一个准确的时间是需要的。

此外,您的服务器上的时间和DB服务器上的时间不需要匹配,如果您的要求很难,那么它们将/可能“永远不匹配”。只有一块坏表每天精确2倍。。。

请注意,在数据库和代码中始终使用UTC日期-时间,这样无论服务器位于何处,您都拥有相同的时间。UTC日期-时间在。NET中有一个ToLocalTime(),而数据库在TSQL中有GetUtcDate(),这样您就不会按时区划分了。

using System;
using System.Runtime.InteropServices;
public static class HighResolutionDateTime 
{ 
    public static bool IsAvailable { get; private set; }
    [DllImport("Kernel32.dll", CallingConvention = CallingConvention.Winapi)] 
    private static extern void GetSystemTimePreciseAsFileTime(out long filetime); 
    public static DateTime UtcNow 
    {
        get { 
            if (!IsAvailable) 
            { 
                throw new InvalidOperationException("High resolution clock isn't available."); 
            } 
            long filetime; 
            GetSystemTimePreciseAsFileTime(out filetime); 
            return DateTime.FromFileTimeUtc(filetime); 
        } 
    } 
    static HighResolutionDateTime() 
    { 
        try 
        { 
            long filetime; 
            GetSystemTimePreciseAsFileTime(out filetime); 
            IsAvailable = true; 
        } 
        catch (EntryPointNotFoundException) 
        {             // Not running Windows 8 or higher.             
            IsAvailable = false;         
        }     
    } 
}

#按照注释编辑关于比较日期-时间,在数据列中使用datetime2(7)作为数据类型,这将与。NET日期时间一样精确