0

在 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
4

1 回答 1

0

作为一种可能的解决方法(不是解决根本问题),请尝试:

... where myDate = CONVERT(VARCHAR(23), @myDate, 21)

我推测日期值正在转换为跨数据库连接上的某些表示形式,该表示形式与精确比较所需的 1/300 秒精度不完全匹配。转换为字符串可能会传递等效于有效的文字(字符串)日期。但效率可能会受到影响。

于 2021-10-28T00:54:55.207 回答