KB2715289 - 修复:在 SQL Server 2008 R2 或 SQL Server 2012 中,当 datetimeoffset 列上有索引时,将 datetimeoffset 列转换为 smalldatetime 列时,出现错误结果

应用对象
SQL Server 2008 R2 Datacenter SQL Server 2008 R2 Developer SQL Server 2008 R2 Enterprise SQL Server 2008 R2 Standard SQL Server 2008 R2 Web SQL Server 2008 R2 Workgroup SQL Server 2012 Business Intelligence SQL Server 2012 Developer SQL Server 2012 Enterprise SQL Server 2012 Standard SQL Server 2012 Web SQL Server 2012 Enterprise Core

Microsoft Microsoft SQL Server 2008 R2 Service Pack 1 (SP1) 修复程序作为一个可下载的文件分发。 由于修补程序是累积的,因此每个新版本都包含前一个 SQL Server 2008 R2 Service Pack 1 (SP1) 修补程序版本中包含的所有修补程序和安全修补程序。

症状

请考虑以下情形:

  • Microsoft SQL Server 2008 R2 或 Microsoft SQL Server 2012 中的表中存在 datetimeoffset 数据类型列。
  • 在 datetimeoffset 列上创建索引。
  • 可以使用不带样式参数的 CAST 或 CONVERT 函数,或者当样式参数的值为 0 时,将 datetimeoffset 数据类型转换为smalldatetime数据类型。
  • CAST 或 CONVERT 函数的结果用于 Transact-SQL 查询的筛选器中。
  • 您运行 Transact-SQL 查询。

在这种情况下,查询返回的结果不正确,因为筛选器未正常工作。 例如,假定名为“Date”的 datetimeoffset 列包含以下值:

  • 2011-05-21 23:00:00 -01:00
  • 2011-05-21 23:00:00 +00:00
  • 2011-05-21 23:00:00 +01:00

运行以下查询:

SELECT Date FROM TestTable WHERE CAST(Date AS smalldatetime)= '2011-05-21 23:00:00'

查询结果只返回一行。 但是,预期结果应返回所有三个值的行。

解决方法

累积更新信息

SQL Server 2012

此问题的修补程序首次在 SQL Server 2012 的累积更新 3 中发布。 有关此累积更新包的更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:

2723749 SQL Server 2012 累积更新包 3注意 由于版本是累积的,因此每个新的修补程序版本都包含之前 SQL Server 2012 修补程序版本中包含的所有修补程序和所有安全修补程序。 Microsoft 建议考虑应用包含此修补程序的最新修补程序版本。 有关更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:

2692828 SQL Server 2012 发布之后发布的 SQL Server 2012 内部版本 必须将 SQL Server 2012 修补程序应用于 SQL Server 2012 的安装。

SQL Server 2008 R2 Service Pack 2

此问题的修补程序首次在 SQL Server 2008 R2 Service Pack 2 的累积更新 1 中发布。 有关如何获取此累积更新包的更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:

2720425 SQL Server 2008 R2 Service Pack 2 的累积更新包 1 注意 由于版本是累积的,因此每个新的修补程序版本都包含之前 SQL Server 2008 R2 修补程序版本中包含的所有修补程序和安全修补程序。 建议应用包含此修补程序的最新修补程序版本。 有关更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:

2730301 在 2008 R2 Service Pack 2 发布之后发布的 SQL Server 2008 R2 内部版本SQL Server

SQL Server 2008 R2 SP1

此问题的修补程序已在累积更新 7 中首次发布。 有关如何获取 SQL Server 2008 R2 Service Pack 1 的此累积更新程序包的更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:

2703282 SQL Server 2008 R2 SP1 的累积更新程序包 7注意 由于版本是累积的,因此每个新的修补程序版本都包含前一个 SQL Server 2008 R2 Service Pack 1 修补程序版本中包含的所有修补程序和安全修补程序。 建议应用包含此修补程序的最新修补程序版本。 有关更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:

2567616 在 SQL Server 2008 R2 SP1 发布之后发布SQL Server 2008 R2 内部版本

详细信息

要重现此问题,请执行以下步骤:

  1. 运行以下查询以创建具有 datetimeoffset 列的表并插入一些记录:

    CREATE TABLE #TestTimeZones (dto datetimeoffset (0) ) ;GO INTO #TestTimeZones (DTO) 值 ('2011-05-21 23:00:00 -01:00') , ('2011-05-21 23:00:00 +00:00') , ('2011-05-21 23:00:00 +01:00') ;GO

  2. 运行以下查询,可以看到返回的结果中正确列出了所有三个值:

    DECLARE @t smalldatetime = '2011-05-21 23:00:00' SELECT dto AS withoutIndex FROM #TestTimeZones WHERE CAST (dto AS smalldatetime) =@t;

  3. 运行以下查询以在“dto”列上创建索引并重复相同的查询:

    CREATE INDEX IX_testTimeZones_Dto ON #TestTimeZones (dto) ;GO -- 重复同一查询 DECLARE @t smalldatetime = '2011-05-21 23:00:00' SELECT dto AS withIndex FROM #TestTimeZones WHERE CAST (dto A smalldatetime) =@t;GO

  4. 再次运行步骤 2 中的查询。 这一次,查询仅返回一行。

  5. 运行以下查询以删除索引和您创建的表:

    在 #TestTimeZones 上删除索引IX_testTimeZones_Dto;去掉塔尔贝 #TestTimeZones;GO

参考资料

有关 CAST 和 CONVERT 函数的更多信息,请转到以下 MSDN 网站:

有关 SQL Server 中 CAST 和 CONVERT 函数的一般信息

状态

Microsoft 已确认在 "适用于" 部分中所列的 Microsoft 产品中存在问题。