仅日期时间可用时在SQL Server中处理日期的正确方法

时间:2019-04-09 08:18:13

标签: sql-server date datetime timezone

我们使用称为“ Aras Innovator”的PLM软件,并且需要将日期存储为自定义项目属性。该软件使用Microsoft SQL Server来存储其数据,并且正式支持在数据库级别上的访问属性。

但是,我们的问题是该软件仅支持日期时间,而不支持日期。 日期存储在UTC中-因此,当我们从中欧的一位客户存储“ 2020-01-01”时,该日期在数据库中变为“ 2019-12-31 23:00”左右(当天午夜前1小时)之前)。并且查询“> = 2020-01-01的查询”因此无法找到这些行。

软件制造商说:

  

没有标准功能只能存储月份和日期;一种   快速的选择可能是将其存储为字符串,然后执行   如果需要,可以对输入的字符串进行编程验证。

     

关于直接SQL查询,所有日期都存储在UTC中,用于   与多个时区的兼容性。他们是自动的   通过标准API访问时进行了转换。直接访问时   对于SQL,您可以使用   Aras Innovator 11.0-CD上的配置国际化指南   图片,第5.3节:

     

选择item_number,innovator.ConvertToLocal(created_on,'Eastern   标准时间”),来自创新者的AS CreatedOn.Document

     

ConvertFromLocal可用于指定您希望查询的日期   而不是要求这些日期以UTC发送。

我不认为使用字符串会是一个好的解决方案。 但不能确信它们的“ ConvertTo / FromLocal”函数也是一个很好的解决方案。 当然,必须有其他方法可以直接在SQL Server中处理此问题?

1 个答案:

答案 0 :(得分:0)

SQL Server 2016引入了AT TIME ZONE statement

考虑:

SELECT CONVERT(date, TheDateTime AT TIME ZONE 'UTC'
                                 AT TIME ZONE 'Central Europe Standard Time')

上面的方法首先将TheDateTime字段从datetime或(datetime2)转换为具有零偏移量(UTC)的datetimeoffset类型。然后它将其转换为Central Europe Standard Time区域,最后将其转换为date类型,删除所有时间信息。

据您的陈述:

  

...> = 2020-01-01”,因此找不到这些行。

您应该考虑转换相反的方向,以便您查询UTC时间-即sargable。例如:

SELECT ...
WHERE TheDateTime >= CONVERT(datetime,
                     '2020-01-01' AT TIME ZONE 'Central Europe Standard Time'
                     AT TIME ZONE 'UTC')

当然,您可以提前在表达式的整个右侧进行操作,而可以使用局部变量。同样,如果您从应用程序中调用此查询,则可以在应用程序代码中转换为UTC,而不必费心在SQL Server中进行操作。