它位于两个按顺序运行的过程中。在过程 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
。
当 Oracle 存储像
2019/5/30 12:02:58
这样的日期值时,它是扔掉毫秒还是只是将其存储在后台而不显示它?在比较
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 进行比较