Oracle 支持 PL/SQL 中的短路评估。然而,在 SQL 中,优化器可以自由地以它想要的任何顺序评估谓词,将谓词推送到视图和子查询中,并以其他方式转换它认为合适的 SQL 语句。这意味着您不应依赖以特定顺序应用的谓词,并使出现在 WHERE 子句中的顺序谓词本质上是不相关的。可用的索引、存在的优化器统计信息、优化器参数和系统统计信息都比 WHERE 子句中谓词的顺序重要得多。
例如,在 PL/SQL 中,您可以使用一个在实际调用时抛出错误的函数来证明这一点。
SQL> ed
Wrote file afiedt.buf
1 create function throw_error( p_parameter IN NUMBER )
2 return number
3 as
4 begin
5 raise_application_error( -20001, 'The function was called' );
6 return 1;
7* end;
SQL> /
Function created.
SQL> ed
Wrote file afiedt.buf
1 declare
2 l_num NUMBER;
3 begin
4 l_num := 1;
5 if( l_num = 2 and throw_error( l_num ) = 2 )
6 then
7 null;
8 else
9 dbms_output.put_line( 'Short-circuited the AND' );
10 end if;
11 if( l_num = 1 or throw_error( l_num ) = 2 )
12 then
13 dbms_output.put_line( 'Short-circuited the OR' );
14 end if;
15* end;
16 /
Short-circuited the AND
Short-circuited the OR
PL/SQL procedure successfully completed.
另一方面,在 SQL 中,操作的顺序由优化器决定,而不是由您决定,因此优化器可以随意短路或不短路。Jonathan Gennick 有一篇很棒的文章Subquery Madness!详细讨论了这一点。在您的特定情况下,如果您在 (FIRST_NAME, HIRE_DATE, STATUS) 上有一个复合索引以及适当的统计信息,优化器几乎肯定会使用该索引来评估前三个条件,然后只调用CALCULATE_INCENTIVE
满足 ID 的函数其他三个标准。如果您在CALCULATE_INCENTIVE(id)
,优化器可能会使用它而不是在运行时调用该函数。但是,如果优化器认为这样做会更有效,那么它可以完全自由地决定在任何一种情况下为每一行调用函数。