Глядя на факторы:
86400 = 24 * 60 * 60 = (2³*3)*(2*3*5)*(2*3*5) = 2<sup>5</sup>*3³*5²
Если ваше число секунд с полуночи не кратно 3³ = 27 (так что у вас просто есть коэффициенты 2 и 5 в делителе), то вы получим повторяющееся число, которое не может быть хорошо выражено в виде десятичного числа, поэтому независимо от точности, в которой Oracle хранит результат SYSDATE - DATE '1970-01-01'
, в какой-то степени будет неточным.
Вы просто необходимо округлить число:
SELECT ROUND((SYSDATE - DATE '1970-01-01')* 86400) FROM DUAL;
Однако, если вы пытаетесь создать unix отметку времени, вам следует использовать:
SELECT ROUND(
(CAST(SYSTIMESTAMP AT TIME ZONE 'UTC' AS DATE) - DATE '1970-01-01') * 86400
)
FROM DUAL;
Поскольку Unix отметки времени находятся в UT C часовой пояс.
Или, если вы хотите сделать это без округления:
SELECT EXTRACT( DAY FROM diff ) * 24 * 60 * 60
+ EXTRACT( HOUR FROM diff ) * 60 * 60
+ EXTRACT( MINUTE FROM diff ) * 60
+ EXTRACT( SECOND FROM diff ) AS unix_timestamp
FROM (
SELECT CAST(SYSTIMESTAMP AS TIMESTAMP(0) WITH TIME ZONE)
- TIMESTAMP '1970-01-01 00:00:00 UTC'
AS diff
FROM DUAL
)
(Приведение используется для удаления дробных секунд, которые SYSTIMESTAMP
обычно имеет.)