应将计算开销小、结果为 FALSE 或 NULL 概率高的条件放在 AND 左侧,因 PL/SQL 短路求值,左侧为假或 NULL 时跳过右侧;credit_ok(cust_id) 等高代价操作必须放右侧。
IF condition1 AND condition2 中,哪个条件该放前面?
必须把计算开销小、结果为 false 或 null 概率高的条件放在 and 左侧。pl/sql 遇到左侧为假就直接跳过右侧,不执行任何求值。
-
credit_ok(cust_id)是远程函数调用或含复杂校验逻辑 → 代价高,必须放后面 loan 是简单数值比较 → 代价低,适合放前面- 若写成
IF credit_ok(cust_id) AND loan ,每次都会触发函数调用,哪怕 <code>loan已超限 - NULL 值会中断短路:如果左侧是
salary > 4000,而salary为NULL,整个表达式结果为NULL,仍不会执行右侧 —— 这和FALSE效果一致,都触发短路
CASE WHEN 的短路只作用于 WHEN 条件,不保护 THEN 表达式
CASE WHEN 的分支判断确实严格从上到下、命中即停,但很多人误以为把危险操作塞进 THEN 就绝对安全。实际是否执行,取决于数据库运行时行为,而非语法位置。
- Oracle 中,
THEN内的 PL/SQL 函数(如json_object()或自定义过程)仅在该分支被选中时才调用,这是安全的 - 但若
THEN中含语法错误(如除零字面量1/0),Oracle 编译阶段可能报错;而运行时短路仍生效,可验证:SELECT CASE WHEN 1=0 THEN 1/0 ELSE 42 END FROM DUAL能正常返回42 - 避免在
WHEN子句里写col = NULL—— 结果恒为UNKNOWN,永远不匹配;必须用col IS NULL - 多个
WHEN都为真时,只取第一个,后续完全不评估,这点和IF-ELSIF一致
DECODE 和 CASE WHEN 在短路行为上没有本质区别
二者在 Oracle 内部都被优化器归一化为相同执行计划节点,短路逻辑也一致:都是顺序判断、命中即止。别指望换 DECODE 来“修复”性能问题。
-
DECODE(col, NULL, 'X', 'Y')对NULL有特例支持,能匹配;但DECODE(col, my_null_var, 'X')不行 —— 因为不是字面量NULL -
CASE WHEN col IS NULL THEN 'X' ELSE 'Y' END是唯一通用、明确、可读的写法 - 嵌套
DECODE(如DECODE(DECODE(...)))不会提升短路效率,只会让维护者数括号数到崩溃 - 所有分支中的表达式(比如每个
THEN里的TO_DATE(str, 'YYYYMMDD'))都只在命中时计算,无需手动提取到外层缓存 —— 除非同一值被多个分支重复使用
高频路径前置不只是习惯,是 Oracle 执行引擎的硬性要求
Oracle PL/SQL 不做分支预测,也不重排条件顺序。它逐条求值 IF / ELSIF / WHEN,直到第一个为 TRUE 的条件出现。这意味着统计上最常走的分支,必须物理上写在最前面。
- 线上日志显示
status = 'processed'占比 87%,但它在ELSIF链中排第三 → 平均要多算两个条件才能进入主逻辑 - 避免用
IS NULL包裹后再比较,比如ISNULL(col, '') != '';改用col IS NOT NULL AND col != '',既显式又利于短路 - 不要在条件中调用耗时函数(如
REGEXP_LIKE或自定义校验),尤其当该函数结果对多数输入都为假时 —— 应先用轻量判断筛一轮 - 若分支内逻辑差异极大(如一个查表、一个只赋常量),高频路径还应尽量减少其内部 I/O,不能只靠“放前面”来掩盖设计缺陷
NULL 在布尔上下文中的三值逻辑表现:它既不是 TRUE 也不是 FALSE,却和 FALSE 一样触发短路。这使得看似安全的条件组合,可能在空值场景下静默跳过关键逻辑。











