为什么在 Firebird 中比较时间戳和日期会产生奇怪的值?

Why comparing Timestamp and date in Firebird result in weird value?

我正在比较一些日期和时间,发现我并不像我想的那样理解Firebird Date Literals and their conversions

请看这个查询:

SELECT 
    iif('2016-01-25' <= '2016-01-25', 1, 0) AS TSCASE,
    iif('2016-01-25 00:00:00.000' <= '2016-01-25', 1, 0) AS TSCASE1,
    iif('2016-01-25 00:00:00.000' <= cast('2016-01-25' as timestamp), 1, 0) AS TSCASE2,
    iif(cast('2016-01-25 00:00:00.000' as timestamp) <= '2016-01-25', 1, 0) AS TSCASE3,
    iif('2016-01-25 00:00:00.000' <= '2016-01-25 00:00:00.000', 1, 0) AS TSCASE4,
    iif('2016-01-25 00:00:00.000' <= '2016-01-25 23:59:59.999', 1, 0) AS TSCASE5,
    iif('2016-01-25 00:00:00.000' <= '2016-01-25  23:59:59.999', 1, 0) AS TSCASE6,
    iif('2016-01-25 00:00:00.000' <= cast('2016-01-25  23:59:59.999' as timestamp), 1, 0) AS TSCASE7
FROM RDB$DATABASE

我希望每一列的结果都是 1。但这是结果:

TSCASE  TSCASE1 TSCASE2 TSCASE3 TSCASE4 TSCASE5 TSCASE6 TSCASE7
       1      0       1       1       1       1       0       1

那么为什么 '2016-01-25 00:00:00.000' <= '2016-01-25' 是假的,但是,当我对 TIMESTAMP 执行任何 cast 时,是真的?

还有为什么'2016-01-25 00:00:00.000' <= '2016-01-25 23:59:59.999''2016-01-25 00:00:00.000' <= cast('2016-01-25 23:59:59.999' as timestamp)是真的,而'2016-01-25 00:00:00.000' <= '2016-01-25 23:59:59.999'是假的?

请注意最后两个表达式中日期和时间之间的额外 space。我确实认为额外的 space 不会改变结果,正如您在 first link:

中看到的那样

White Space in Date Literals

Spaces or tabs can appear between elements. A date part must be separated from a time part by at least one space.

问题是您没有在大多数表达式中比较时间戳和日期。相反,您正在比较 string (CHAR) 文字。

回答您的具体问题:

  1. '2016-01-25 00:00:00.000' <= '2016-01-25' 是假的,因为在字符串排序中 2016-01-252016-01-25 00:00:00.000
  2. 之前
  3. '2016-01-25 00:00:00.000' <= '2016-01-25 23:59:59.999' 为假,因为 2016-01-25 23:59:59.999 在时间部分之前有第二个 space,而在字符串排序中 space 在 0 之前。

要使用日期或时间戳字面量,您要么需要在字符串字面量前显式添加 DATETIMESTAMP 前缀,要么需要使用强制转换,否则它只是一个字符串。将您的查询更改为以下查询,您确实得到了预期值:

SELECT 
    iif(DATE'2016-01-25' <= DATE'2016-01-25', 1, 0) AS TSCASE,
    iif(TIMESTAMP'2016-01-25 00:00:00.000' <= DATE'2016-01-25', 1, 0) AS TSCASE1,
    iif(TIMESTAMP'2016-01-25 00:00:00.000' <= cast('2016-01-25' as timestamp), 1, 0) AS TSCASE2,
    iif(cast('2016-01-25 00:00:00.000' as timestamp) <= DATE'2016-01-25', 1, 0) AS TSCASE3,
    iif(TIMESTAMP'2016-01-25 00:00:00.000' <= TIMESTAMP'2016-01-25 00:00:00.000', 1, 0) AS TSCASE4,
    iif(TIMESTAMP'2016-01-25 00:00:00.000' <= TIMESTAMP'2016-01-25 23:59:59.999', 1, 0) AS TSCASE5,
    iif(TIMESTAMP'2016-01-25 00:00:00.000' <= TIMESTAMP'2016-01-25  23:59:59.999', 1, 0) AS TSCASE6,
    iif(TIMESTAMP'2016-01-25 00:00:00.000' <= cast('2016-01-25  23:59:59.999' as timestamp), 1, 0) AS TSCASE7
FROM RDB$DATABASE