我们已经运行 SQL Server 2016 一段时间了,但最初将数据库兼容性级别保留为 SQL Server 2008 (100)。最近我们确实将数据库兼容级别更新为 2016 (130),但我们在那里遇到的问题很少。我们设法找到了一个特定的查询,其中查询将 datetime 转换为 datetime2,当它应该返回一个值时它返回 NULL,不确定它是 CE 还是什么?请看下面的例子:
CREATE TABLE TestCE
(
Id INT IDENTITY(1,1),
CurrentDateTime DATETIME
)
GO
INSERT dbo.TestCE(CURRENTDATETIME)
SELECT GETDATE()
UNION ALL SELECT '2018-04-11 08:44:42.643'
UNION ALL SELECT '2018-04-12 09:49:45.334'
GO
SELECT * FROM TestCE
--The resultset
1 2018-04-17 16:49:02.813
2 2018-04-11 08:44:42.643
3 2018-04-12 09:49:45.333
但是当我运行以下查询时,没有得到任何结果:
SELECT * FROM TESTCE
WHERE CURRENTDATETIME = CONVERT(DATETIME2, '2018-04-12 09:49:45.333')
GO
SELECT * FROM TESTCE
WHERE CURRENTDATETIME = CONVERT(DATETIME2, '2018-04-11 08:44:42.643')
GO
SELECT * FROM TESTCE
WHERE CURRENTDATETIME = CONVERT(DATETIME2, '2018-04-17 16:49:02.813')
我也尝试过使用 QueryTraceOn 选项来实现后向 CE,但没有成功:
SELECT * FROM TESTCE
WHERE CURRENTDATETIME = CONVERT(DATETIME2, '2018-04-12 09:49:45.333')
OPTION(QUERYTRACEON 9481);
GO
SELECT * FROM TESTCE
WHERE CURRENTDATETIME = CONVERT(DATETIME2, '2018-04-11 08:44:42.643')
OPTION(QUERYTRACEON 9481);
GO
SELECT * FROM TESTCE
WHERE CURRENTDATETIME = CONVERT(DATETIME2, '2018-04-17 16:49:02.813')
OPTION(QUERYTRACEON 9481);
还设置了以下数据库选项,但也没有成功:
ALTER DATABASE SCOPED CONFIGURATION
SET LEGACY_CARDINALITY_ESTIMATION = ON
一旦我将兼容级别改回 2008,查询就会开始按预期返回数据。
从这篇知识库文章:
在您的具体示例中,如果出现以下情况,比较仍然有效:
datetime2
(这是不必要的,因为你在输入中没有更多的精度);datetime2
列开始;datetime
在转换为之后将输入转换为datetime2
;或者,否则你试图让 SQL Server 永远知道,例如
.333
=.334
。新类型是在 SQL Server 2008 中引入的,并被替换以解决此类不精确问题;我猜他们觉得他们必须在某个时候继续前进。顺便说一句,我不认为当前的行为是 100% 正确的,但这是我们目前所坚持的。
此外,兼容性级别是影响基数估计模型的一种方式(并不是真正好的方式),但反之则不然。您不能通过更改 CE 模型来更改兼容级别。这就是您使用查询级跟踪标志或数据库配置选项没有取得任何成功的原因。但你不必回到
100
;120
可能也会起作用。