【问题标题】:SQL Server 2016 : join DATETIME2(3) with DATETIMESQL Server 2016:加入 DATETIME2(3) 和 DATETIME
【发布时间】:2019-10-07 19:27:13
【问题描述】:

在 SQL Server 2016 中使用 PK 加入 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

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

但如果我删除 PK 或将兼容性级别更改为 COMPATIBILITY_LEVEL = 120,那么我会按预期获得所有行

这是一个错误吗?

有没有更好的方法来做这个加入。

注意:我加入同一个表只是为了在现实生活中我加入两个不同的表之间的示例。

【问题讨论】:

标签: sql datetime sql-server-2016 datetime2


【解决方案1】:

其实我也遇到过。对于 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,如果上述查询对您有用,您现在可以告诉我吗?
  • 对于以下数据,您可能会得到错误的结果:INSERT INTO DATETIME_TEST ([DATETIME], [DATETIME2_3]) VALUES ('20020202 02:02:02.003', '20020202 02:02:02.002' );由于 002 毫秒被四舍五入为 003。
  • hmmm .. 但不管您是否尝试转换,DATETIME 都不是这样吗?例如。执行这个:
  • 删除表如果存在 DATETIME_TEST;创建表 DATETIME_TEST ( [DATETIME] DATETIME NOT NULL, [DATETIME2_3] DATETIME2(3) ); ALTER TABLE DATETIME_TEST 添加约束 PK_DATETIME_TEST PRIMARY KEY ([DATETIME]);插入 DATETIME_TEST ([DATETIME], [DATETIME2_3]) 值 ('20020202 02:02:02.003', '20020202 02:02:02.003'), ('20020206 02:02:02.056', '20020206 02:02:02. ');选择 * FROM DATETIME_TEST; SELECT * FROM DATETIME_TEST WHERE CONVERT(DATETIME2(3), [DATETIME]) = [DATETIME2_3];
  • 当我检查 SQL 语句结果时,我会将其与表中的现有行进行比较,而不是与我尝试插入的行进行比较。因此,WHERE CONVERT(DATETIME2(3), [DATETIME]) = [DATETIME2_3] 会为您带来正确的结果。
猜你喜欢
  • 2010-11-22
  • 1970-01-01
  • 2016-11-30
  • 1970-01-01
  • 1970-01-01
  • 2011-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多