没有与Oracle功能的短路OR?

Bri*_*ser 1 sql oracle plsql short-circuiting

要允许超级用户/管理员登录我的系统,我正在运行(更大版本)此查询:

Select *
  From mytable
 Where (:id = 'Admin' Or :id = mytable.id);
Run Code Online (Sandbox Code Playgroud)

如果我传递用户ID,我会获得该用户的所有数据; 如果我传递字符串'Admin',我会得到所有数据.这是有效的,因为Oracle的OR是一个短路运算符.

但是,如果我将'Admin'作为一个包常量并使用函数来获取它,就像这样

Select *
  From mytable
 Where (:id = mypackage.GetAdminConstant Or :id = mytable.id);
Run Code Online (Sandbox Code Playgroud)

ORA-01722: invalid number当我通过'Admin'时,我得到了.

当我引入函数时,为什么OR会失去其短路方面?

Dav*_*sta 6

它不会失去短路方面.但SQL不是一种过程语言,并且不能保证多个谓词的评估顺序.

在C中,如果您编写a || b,您知道a将首先进行评估,然后b仅在必要时进行评估.

在SQL中,如果你写的a OR b,你只知道,要么ab将首先评估,以及其他的表达(至少在甲骨文)将只在必要时进行评估.

查看两个查询的执行计划可能会给出评估顺序的一些指示,或者可能没有.

我猜想,在第一种情况下,Oracle可以看到第一个表达式对于每一行都具有相同的值,因此首先对其进行求值.当您更改为第二种情况时,Oracle现在会看到一个函数,每次计算时都会有不同的结果,因此它必须检查每一行,因此它会在执行函数调用之前尝试对列执行简单的相等性检查.

我想知道如果你标记函数DETERMINISTIC你会得到不同的结果,所以Oracle会知道它本质上是一个常数.