我有一个简单的表,由5条记录组成,差别为毫秒。 将我的数据库从 2016升级到2017 SQL服务器时,我遇到了问题。 这里附有两个图像,比较2016年和2017年SQL服务器结果的结果。我不明白2017年为什么会出现这种不良行为。
这是2017 SQL服务器中的错误吗? ?
表格列数据类型在这两种情况下都相同 datetime 数据类型。
这是create table查询。
USE [Test]
GO
CREATE TABLE [dbo].[TestVisionBot3](
[FileId] [varchar](50) NULL,
[OrgId] [nchar](10) NOT NULL,
[ProjectId] [varchar](50) NULL,
[CreatedAt] [datetime] NULL,
[LockedUserid] [nvarchar](50) NULL
) ON [PRIMARY]
GO
以下是样本数据。
1a 1 2a 2018-04-29 10:30:30.010 test
3a 1 2a 2018-04-29 10:30:30.553 test
2a 1 2a 2018-04-29 10:30:30.557 test
4a 1 2a 2018-04-29 10:30:30.560 test
5a 1 2a 2018-04-29 10:30:30.563 test
答案 0 :(得分:5)
背景资料:
<强> Precedence rule 强>
当运算符组合了两个不同数据类型的表达式时,数据类型优先级的规则指定优先级较低的数据类型转换为具有较高优先级的数据类型。
因此,在你将datetime与datetime2进行比较的where子句的情况下,datetime被提升到datetime2,因为datetime2具有更高的优先级。
现在SQL Server 2017会发生什么变化?在新版本的SQL Server中,隐式转换将遵循从datetime到datetime2的转换规则,如下所述
<强> Conversion from datetime to datetime2 rule: 强>
转换来自datetime时,会复制日期和时间。分数精度扩展到7位数。以下示例显示将datetime值转换为datetime2值的结果。
DECLARE @datetime datetime = '2018-04-29 10:30:30.553';
DECLARE @datetime2 datetime2 = @datetime;
SELECT @datetime2 AS '@datetime2', @datetime AS '@datetime';
--Result
--@datetime2 @datetime
------------------------- ---------------------------
--22018-04-29 10:30:30.5533333 2018-04-29 10:30:30.553
现在您之前的转换实际上是datetime2转换的字符串文字。所以它遵循不同的规则。
字符串文字到datetime2转换规则:
时间的字符串部分被分配给日期的时间和日期,没有外推精度,而是右边填充0,以获得额外的精度。 顺便提一下,这也是在sql server 2017之前的版本中进行datetime到datetime2转换。
更多解释 当您转换为&#39; 2018-04-29 10:30:30.553&#39;到datetime2它到达2018-04-29 10:30:30.5530000&#39;因为它将字符串文字转换为datetime2
当您将存储的日期时间值与where子句中的datetime2值进行比较时,将应用优先规则,因此datetime将被提升为datetime2。所以当&#39; 2018-04-29 10:30:30.5530000&#39; (日期时间值)被提升到Datetime2值,然后小数部分被增强并且变得比原来那样大。
因此您的.553扩展为.553333,大于.533
DECLARE @datetime datetime = '2018-04-29 10:30:30.553';
DECLARE @strliteral varchar(max)='2018-04-29 10:30:30.553';
DECLARE @datetime2 datetime2 = @datetime;
SELECT
@datetime2 AS '@datetime2',
@datetime AS '@datetime',
cast(@strliteral as datetime2) AS strtoDatetime2,
cast(@datetime as datetime2) AS datetimetoDatetime2;
-- @datetime2 @datetime strtoDatetime2
datetimetoDatetime2
-- 2018-04-29 10:30:30.5533333 2018-04-29 10:30:30.553 2018-04-29 10:30:30.5530000 2018-04-29 10:30:30.5533333