在SQL中比较两个日期时oracle的准确性



它位于两个按顺序运行的过程中。在过程 1 中,系统时间的运行时间戳为2019/5/30 12:02:58.100。sql 如下

insert into A(xxx,xxx,cdate) values(xxx,xxx,sysdate)

我发现这个插入行的 cdate 字段是2019/5/30 12:02:58,没有毫秒。

然后过程运行两次,系统时间的运行时间戳为2019/5/30 12:02:58.200。该 SQL 如下

select xxx from A where cdate<sysdate

这将返回无结果。这很奇怪,因为我刚刚插入了一行带有 cdate2019/5/30 12:02:58.这应该小于sysdate

  1. 当 Oracle 存储像2019/5/30 12:02:58这样的日期值时,它是扔掉毫秒还是只是将其存储在后台而不显示它?

  2. 在比较cdate<sysdate时,它使用哪两个值?我猜它正在使用2019/5/30 12:02:58 < 2019/5/30 12:02:58,所以这返回 false。

当 Oracle 存储像2019/5/30 12:02:58这样的日期值时,它是扔掉毫秒还是只是将其存储在后台而不显示它?

日期值没有任何要丢弃的毫秒分量。sysdate返回 DATE 数据类型:

此数据类型包含日期时间字段年、月、日、小时、分钟和秒。它没有秒数或时区。

在您的过程中,您正在查看时间戳值:

此数据类型包含日期时间字段年、月、日、小时、分钟和秒。它包含秒的小数部分,但没有时区。

。或具有时区的变体,例如带有时区的时间戳,由systimestamp返回:

此数据类型包含日期时间字段年、月、日、小时、分钟、秒、TIMEZONE_HOUR和TIMEZONE_MINUTE。它有秒的小数部分和明确的时区。


在比较cdate<sysdate时,它使用哪两个值?我猜它正在使用2019/5/30 12:02:58 < 2019/5/30 12:02:58,所以这返回 false。

由于您的插入语句使用的是sysdate,因此此时cdate是否定义为DATE或TIMESTAMP并不重要,如果是后者,则小数秒部分只是被截断为零。sysdate还返回一个 DATE,所以是的,它正在执行:

2019-05-30 12:02:58 < 2019-05-30 12:02:58

2019-05-30 12:02:58.000 < 2019-05-30 12:02:58

这可能涉及隐式强制转换。无论哪种方式,结果确实是错误的。


如果要比较可能在同一秒内的值,则必须使用 TIMESTAMP。根据需要将列定义为 TIMESTAMP 变体之一,然后在插入和比较中使用systimestamp而不是sysdate。这一切都必须是时间戳 - 如果您所做的任何部分保留为日期,那么在某个时候,小数秒将丢失,您将处于与现在相同的位置。

如果您的列是 DATE 类型,则它不存储毫秒。SYSDATE也不会返回它们。确保您的列是具有适合分数精度的数字的时间戳,以存储所需的毫秒数,并确保将其与 SYSTIMESTAMP 进行比较

最新更新