当前位置: 首页 > 知识库问答 >
问题:

系统印章和系统印章的奇怪行为

习淇
2023-03-14

今天我遇到了一个我无法解释的情况,我希望你能解释。

归结起来就是:

比如说函数sleep()返回数字 循环10秒,然后返回1。

像这样的sql查询

SELECT systimestamp s1, sleep(), systimestamp s2 from dual;

将为s1和s2生成两个相同的值。所以这有点优化了。

一个PLSQL块

a_timestamp := systimestamp + 5sec;
IF systimestamp < a_timestamp and sleep() = 1 and systimestamp > a_timestamp THEN 
  [...] 
END IF;

将求值为true,因为表达式从左到右求值,并且由于sleep()的原因,第二个systimestamp比第一个systimestamp大10秒,并且一个_时间戳位于两者之间。5秒的语法是伪代码,但请耐心听我说。因此,这里的systimestamp没有得到优化。

但现在它变得很时髦:

IF systimestamp between systimestamp and systimestamp THEN [...]

都是假的,但是

IF systimestamp + 0 between systimestamp + 0 and systimestamp + 0 THEN [...]

总是真实的。

为什么?我很困惑。。。

Sysdate也会发生这种情况


共有2个答案

宇文德明
2023-03-14

如果您在时间戳中添加一个数字,您不会得到时间戳...你会得到一个日期。因此,您已经删除了小数秒部分,因此看起来应该相等的比较可能不相等

SQL> select systimestamp, systimestamp+0 from dual;

SYSTIMESTAMP                                                                SYSTIMESTAMP+0
--------------------------------------------------------------------------- -------------------
18-JUN-20 11.57.28.350000 AM +08:00                                         18/06/2020 11:57:28

SQL> select * from dual where systimestamp > sysdate;

D
-
X

如果要在时间戳中添加天数等,请使用间隔数据类型,而不是数字。

潘哲
2023-03-14
匿名用户

当你这样做时:

if systimestamp between systimestamp and systimestamp then

非确定性的systimestamp调用只被评估了三次,每次得到的结果都略有不同。

你可以看到同样的效果

if systimestamp >= systimestamp then

它也总是返回false。

然而,这并不总是如此。如果服务器速度足够快,并且/或者它所在的平台对于时间戳分数秒的精度足够低(例如在视窗系统上,我相信它仍然将精度限制在毫秒),那么所有这些调用在某些时候或大部分时间仍然可以获得相同的值。

SQL中的情况有些不同;作为等价物:

select *
from dual
where systimestamp between systimestamp and systimestamp;

将始终返回一行,因此条件始终为真。文件中明确提到:

返回当前系统日期时间信息的所有datetime函数,例如SYSDATE、SYSTIMESTAMP、current_TIMESTAMP等,对于每个SQL语句都会计算一次,而不管它们在该语句中被引用了多少次。

PL/SQL中没有这样的限制/优化(取决于您如何看待它)。当你在之间使用时,它会说:

a和b之间的表达式x的值定义为与表达式(x)的值相同

SQL参考资料还提到:

在SQL中,expr1可能会被多次计算。如果BETWEEN表达式出现在PL/SQL中,则expr1保证只计算一次。

但是它没有提到跳过a和b(或expr2或expr3)的计算,即使是在PL/SQL中的系统日期时间函数。

因此,将对中间的中的所有三个表达式求值,它将对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

(初始时间)

您的其他示例都以删除小数秒的方式操作时间戳,将部分或全部结果转换为日期,如@Connor所示(我在评论中提到)。这些都与您的核心问题无关,即为什么如果systimestamp和systimestamp之间的systimestamp那么通常是错误的。

 类似资料:
  • Linux系统服务管理 从CentOS7开始,CentOS的服务管理工具由SysV改为了systemd,但即使是在CentOS7里,也依然可以使用chkconfig这个原本出现在SysV里的命令。 Systemd的设计目标是,为系统的启动和管理提供一套完整的解决方案。 chkconfig服务管理工具 罗列chkconfig所管理的服务 使用chkconfig --list命令可以列出所有的服务及其

  • 第六章 文件系统 文件系统的目的是组织和存储数据,典型的文件系统支持用户和程序间的数据共享,并提供数据持久化的支持(即重启之后数据仍然可用)。 xv6 的文件系统中使用了类似 Unix 的文件,文件描述符,目录和路经名(请参阅第零章),并且把数据存储到一块 IDE 磁盘上(请参阅第三章)。这个文件系统解决了几大难题: 该文件系统需要磁盘上数据结构来表示目录树和文件,记录每个文件用于存储数据的块,以

  • Evan Sarmiento 版权 © 2001 Evan Sarmiento 在大多数UNIX®系统中,用户root是万能的。这也就增加了许多危险。 如果一个攻击者获得了一个系统中的root,就可以在他的指尖掌握系统中所有的功能。 在FreeBSD里,有一些sysctl项削弱了root的权限, 这样就可以将攻击者造成的损害减小到最低限度。这些安全功能中,有一种叫安全级别。 另一种在FreeBSD

  • 根据 X.Org 的 X11 服务修改此文档 Ken Tom 和 Marc Fonvieille. 6.1. 概述 FreeBSD 使用 X11 来为用户提供功能强大的图形用户界面。X11 是一种可以免费使用的 X 视窗系统,其实现包括 XorgFreeBSD 中默认使用并受官方支持的 X11 实现即是Xorg, 它是由 X.Org基金会开发的 X11 服务, 采用与 FreeBSD 类似的授权。

  • Debian 的设计目标之一就是提供一致的升级途径和安全的升级过程. 我们一直尽力于平滑升级过程的实现. 如果升级过程中软件包将会对重要的注意事项警告用户, 并提供一个可能的解决方法. 你也应该阅读 Debian CD 上的发行记录, 该文档对升级作了详细描述,也可从http://www.debian.org/releases/stable/releasenotes处获得该文档. 8.1 把基于