SQL Server 2016: 使用join将DATETIME2(3)与DATETIME连接

6

我在 SQL Server 2016 中使用 DATETIME2(3)DATETIME 视图创建主键时,联接出现了意外的结果。

我有以下表格:

CREATE TABLE DATETIME_TEST 
(
    [DATETIME] DATETIME NOT NULL,
    [DATETIME2_3] DATETIME2(3)
);

ALTER TABLE DATETIME_TEST 
    ADD CONSTRAINT PK_DATETIME_TEST PRIMARY KEY ([DATETIME]);

INSERT INTO DATETIME_TEST ([DATETIME], [DATETIME2_3])
VALUES ('20020202 02:02:02.000', '20020202 02:02:02.000'), 
       ('20020202 02:02:02.003', '20020202 02:02:02.003'), 
       ('20020202 02:02:02.007', '20020202 02:02:02.007'),
       ('2019-04-28 07:23:29.447', '2019-04-28 07:23:29.447');

SELECT * 
FROM DATETIME_TEST 
WHERE CONVERT(DATETIME2(3), [DATETIME]) = [DATETIME2_3]

结果如下:
DATETIME                  DATETIME2_3
-------------------------------------------------
2002-02-02 02:02:02.000   2002-02-02 02:02:02.000
2002-02-02 02:02:02.003   2002-02-02 02:02:02.003
2002-02-02 02:02:02.007   2002-02-02 02:02:02.007
2019-04-28 07:23:29.447   2019-04-28 07:23:29.447

如上所述,这些值是相等的。

SELECT      
    a.DATETIME,
    a.DATETIME2_3
FROM
    DATETIME_TEST a
INNER JOIN 
    DATETIME_TEST b ON CONVERT(DATETIME2(3), a.[DATETIME]) = b.[DATETIME2_3]

结果如下:
DATETIME2_3                  DATETIME
-----------------------------------------------------
2002-02-02 02:02:02.000      2002-02-02 02:02:02.000

虽然值相等,但我只得到了一些行。

但是,如果我删除主键或将兼容性级别更改为COMPATIBILITY_LEVEL = 120,那么我会如预期地获取所有行。

这是一个错误吗?

有没有更好的方法来进行这个连接操作。

注意:我只是为了示例方便而连接到相同的表,在实际生活中,我连接的是两个不同的表。


可能是为什么从DATETIME转换为DATETIME2似乎会改变值?的重复问题。 - Dan Guzman
@DanGuzman 这不是重复,因为该帖子比较了 DATETIME(7) 和 DATETIME。在我的帖子中,我理解隐式转换不起作用。因此,我进行了显式转换,但由于存在 PK,联接失败。 - Ida Amit
我已经在https://feedback.azure.com/forums/908035-sql-server/suggestions/37717732-wrong-results-when-selecting-sqlserver2016-join-da上提交了一个错误报告。 - Ida Amit
感谢您抽出时间创建错误报告,已点赞。 - Dan Guzman
1个回答

0

实际上,我也遇到过这个问题。这绝对是向Microsoft SQL Server团队提出的一个有效问题。感谢您抽出时间来报告此错误。

但作为替代方案,您应该尝试将“更丰富”的数据类型(DATETIME2)转换为“较差”的数据类型(DATETIME),以实现向后兼容的方式。然后它会给您想要的结果:

SELECT      
    a.DATETIME,
    a.DATETIME2_3
FROM
    DATETIME_TEST a
INNER JOIN 
    DATETIME_TEST b ON a.[DATETIME] = CONVERT(DATETIME, b.[DATETIME2_3])

@Ida Amit,您能否告诉我上面的查询是否对您有用? - san
以下数据可能会导致错误的结果:INSERT INTO DATETIME_TEST ([DATETIME], [DATETIME2_3]) VALUES ('20020202 02:02:02.003', '20020202 02:02:02.002'); 因为002毫秒被四舍五入为003。 - Ida Amit
嗯...但无论你是否尝试转换,DATETIME都是这种情况吗?例如,执行以下操作: - san
DROP TABLE IF EXISTS DATETIME_TEST;CREATE TABLE DATETIME_TEST ( [DATETIME] DATETIME NOT NULL, [DATETIME2_3] DATETIME2(3) );ALTER TABLE DATETIME_TEST ADD CONSTRAINT PK_DATETIME_TEST PRIMARY KEY ([DATETIME]);INSERT INTO DATETIME_TEST ([DATETIME], [DATETIME2_3]) VALUES ('20020202 02:02:02.003', '20020202 02:02:02.003'), ('20020206 02:02:02.056', '20020206 02:02:02.056'); SELECT * FROM DATETIME_TEST;SELECT * FROM DATETIME_TEST WHERE CONVERT(DATETIME2(3), [DATETIME]) = [DATETIME2_3]; - san
当我检查SQL语句的结果时,我将其与表中现有的行进行比较,而不是与我尝试插入的内容进行比较。因此,WHERE CONVERT(DATETIME2(3), [DATETIME]) = [DATETIME2_3] 可以带来正确的结果。 - Ida Amit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接