我最近了解到,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或方法。
您会发现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日期时间一样精确