Когда вы делаете:
if systimestamp between systimestamp and systimestamp then
недетерминированный c systimestamp
вызов просто оценивается три раза и каждый раз дает очень немного разные результаты.
Вы можно увидеть тот же эффект с
if systimestamp >= systimestamp then
, который также всегда возвращает false.
За исключением того, что это не всегда. Если сервер достаточно быстрый и / или платформа, на которой он работает, имеет достаточно низкую точность для дробных секунд временной метки (т.е. на Windows, что, как я считаю, по-прежнему ограничивает точность до миллисекунд), тогда все эти вызовы могут получить то же значение иногда или большую часть времени.
В SQL все немного иначе; как эквивалент:
select *
from dual
where systimestamp between systimestamp and systimestamp;
всегда будет возвращать строку, поэтому условие всегда истинно. Это явно упоминается в документации :
Все функции datetime, которые возвращают текущую системную информацию о дате и времени, такую как SYSDATE, SYSTIMESTAMP, CURRENT_TIMESTAMP и т. Д., Оцениваются один раз. для каждого оператора SQL, независимо от того, сколько раз они упоминаются в этом операторе.
В PL / SQL нет такого ограничения / оптимизации (в зависимости от того, как вы на это смотрите). Когда вы используете between
, он говорит :
Значение выражения x BETWEEN a AND b определяется как такое же, как значение выражения (x> = a) И (x <= b). Выражение x будет вычислено только один раз. </p>
и SQL ссылка также упоминает, что :
В SQL, это возможно, что expr1 будет оцениваться более одного раза. Если выражение BETWEEN появляется в PL / SQL, expr1 гарантированно оценивается только один раз.
, но ничего не говорит о пропуске вычисления a и b (или expr2 или expr3 ) даже для системных функций datetime в PL / SQL.
Итак, все три выражения в ваш between
будет оценен, он сделает три отдельных вызова systimestamp
, и все они (обычно) получат несколько разные результаты. Фактически вы получите:
if initial_time between initial_time + 1 microsecond and initial_time + 2 microseconds then
или, другими словами,
if (initial_time >= initial_time + 1 microsecond) and (initial_time <= initial_time + 2 microseconds) then
Хотя (initial_time <= initial_time + 2 microseconds)
всегда будет истинным, (initial_time >= initial_time + 1 microsecond)
должно быть ложным - если только интервал между первой и третьей оценками фактически равен нулю для этой платформы / сервера / вызова. Когда он равен нулю, условие оценивается как истинное; в остальное время, когда есть какая-либо измеримая задержка, она будет оцениваться как ложь.
Все ваши другие примеры манипулируют меткой времени таким образом, что удаляют доли секунды, поворачивая некоторые или все результаты в даты, как показал @Connor (и я упоминал в комментариях). Это на самом деле не имеет отношения к вашему основному вопросу о том, почему if systimestamp between systimestamp and systimestamp then
(обычно) ложно.