在 Azure SQL 数据库中,我们使用外部表从另一个 Azure SQL 数据库中查询数据。按 DATETIME 列过滤外部表时,如果毫秒的最后一位是 3 或 7,则不返回任何行。如果最后一位是 0,则查询按预期工作。
例子:
/* MILLISECONDS ENDS WITH 0 - WORKS AS EXPECTED*/
DECLARE @myDate DATETIME = '2021-10-27 12:00:00.000';
SELECT * from dbo.ext_datetimetest where myDate = @myDate;
GO
/* MILLISECONDS ENDS WITH 3 OR 7 - RETURNS NOTHING*/
DECLARE @myDate DATETIME = '2021-10-27 12:00:00.003';
SELECT * from dbo.ext_datetimetest where myDate = @myDate;
GO
笔记:
- 只有参数化的查询受到影响。在 where 子句中硬编码日期时间值的任何查询都按预期工作。
- 只有跨数据库查询受到影响。直接在源数据库上运行查询按预期工作。
- 我们的代码多年来一直按预期工作,上周才开始出现这种行为。
- 这仅在我们的测试和生产环境中发生。我们的开发环境对所有日期时间值都按预期工作。
重现步骤:
/* EXECUTE IN DATABASE #1 */
CREATE TABLE dbo.datetimetest (myDate DATETIME NOT NULL);
GO
INSERT dbo.datetimetest (myDate)
VALUES
('2021-10-27 12:00:00.000')
,('2021-10-27 12:00:00.003')
,('2021-10-27 12:00:00.007')
,('2021-10-27 12:00:00.010')
;
GO
/* EXECUTE IN DATABASE #2 */
CREATE EXTERNAL TABLE dbo.ext_datetimetest ( myDate DATETIME NOT NULL)
WITH (DATA_SOURCE = [DATABASE #1], SCHEMA_NAME = N'dbo', OBJECT_NAME = N'datetimetest');
GO
/* SELECT ALL ROWS TO CONFIRM VALUES */
SELECT * FROM dbo.ext_datetimetest;
/* These all work because the filters are hardcoded */
SELECT * from dbo.ext_datetimetest where myDate = '2021-10-27 12:00:00.000';
SELECT * from dbo.ext_datetimetest where myDate = '2021-10-27 12:00:00.003';
SELECT * from dbo.ext_datetimetest where myDate = '2021-10-27 12:00:00.007';
SELECT * from dbo.ext_datetimetest where myDate = '2021-10-27 12:00:00.010';
GO
/* VARIABLES ONLY WORK IF LAST DIGIT IS 0 */
DECLARE @myDate DATETIME;
SET @myDate = '2021-10-27 12:00:00.000'; SELECT * from dbo.ext_datetimetest where myDate = @myDate; /* WORKS */
SET @myDate = '2021-10-27 12:00:00.003'; SELECT * from dbo.ext_datetimetest where myDate = @myDate; /* RETURNS NOTHING */
SET @myDate = '2021-10-27 12:00:00.007'; SELECT * from dbo.ext_datetimetest where myDate = @myDate; /* RETURNS NOTHING */
SET @myDate = '2021-10-27 12:00:00.010'; SELECT * from dbo.ext_datetimetest where myDate = @myDate; /* WORKS */
GO