CASE WHEN 严格从上到下求值,遇首个TRUE条件即返回对应THEN值,后续分支不执行;但THEN/ELSE表达式仅在被选中时求值,不同数据库对短路的支持程度存在差异。
CASE WHEN 的求值顺序是严格从上到下,遇到第一个为 TRUE 的条件即返回对应 THEN 结果
SQL 标准规定
表达式必须按书写顺序逐个判断
条件,一旦某个条件求值为
(注意:不是非空或非零),就立即返回其
子句的值,后续
不再计算。这本质上就是短路求值。
常见误解是认为“所有条件会并行预计算”,其实不会——数据库引擎会在运行时跳过后续分支。但要注意:这个短路只作用于条件判断逻辑本身,不保护
或
中的表达式提前执行(见下一条)。
若多个
条件都为
,只取第一个匹配项,其余忽略
与任何值比较(如
)结果为
,不触发该分支;要用
显式判断
条件中含函数调用(如
)时,仅当该分支被选中才会执行,可用来规避空值报错
THEN 和 ELSE 中的表达式不是短路保护的——它们只在被选中时才求值
很多人误以为把危险操作(比如除零、JSON 解析、类型转换)塞进
就能靠短路避免报错。实际上,这些表达式确实不会在未命中分支时执行——但前提是:它们**不被优化器提前展开或预编译失败**。
不同数据库行为有差异:
PostgreSQL 通常安全:未选中的
内部表达式完全不执行
MySQL 5.7+ 在多数情况下也遵守短路,但若表达式含子查询或 UDF,可能因优化器行为意外触发
SQL Server 更激进:某些版本会对所有
分支做类型推导甚至预执行检查,导致
报错即使该分支永远不走
Oracle 对
中的 PL/SQL 函数仍会做语法校验,但运行时短路有效
验证方式很简单:
—— 正常返回
才说明当前数据库支持分支级短路。
php版微信js-sdk支付接口类
php版微信js-sdk支付接口类
下载
嵌套 CASE 或混合 AND/OR 容易破坏预期短路路径
当你在单个
子句里写复杂逻辑,比如
,那么即使
为
,部分数据库(尤其是 MySQL)可能仍会尝试解析
并抛出语法错误——因为 JSON 函数要求参数为合法 JSON 字符串,而
或非 JSON 值会导致早期失败。
解决办法是拆成嵌套
,先确保输入安全:
避免在
中直接调用可能崩溃的函数;优先用标量判断(
、
、
)做过滤
用
或
预处理参数,比依赖短路更可控
WHERE 子句里的 CASE 短路行为不可靠,别这么用
有人试图写
来动态过滤,这看似聪明,但实际风险很大:
优化器可能重排执行顺序,先把
应用到所有行,再套
,导致非
js
on 类型数据报错
即使短路生效,
在非字符串输入上仍可能返回
而非
,使整个条件变为
,被
当作不匹配(符合预期),但语义已模糊
更稳妥的方式是用布尔逻辑:
真正需要动态类型处理时,应优先考虑生成列、物化视图或应用层分流——SQL 的短路不是防错保险丝,只是执行路径的节流阀。
CASEWHENTRUETHENWHENTHENELSEWHENTRUENULLcol = NULLUNKNOWNIS NULLLENGTH(col)THENTHENTHEN/ELSE1/0THENSELECT CASE WHEN 1=0 THEN 1/0 ELSE 42 END;42WHENWHEN col IS NOT NULL AND JSON_EXTRACT(col, '$.id') > 10col IS NOT NULLFALSEJSON_EXTRACTNULLCASECASE WHEN col IS NOT NULL THEN
CASE WHEN col REGEXP '^\{.*\}$' THEN JSON_EXTRACT(col, '$.id') > 10 ELSE FALSE END
ELSE FALSE ENDWHENIS NULLREGEXPLENGTHCOALESCENULLIFWHERE CASE WHEN type='json' THEN JSON_VALID(content) ELSE TRUE ENDJSON_VALID(content)CASEJSON_VALIDNULLFALSEUNKNOWNWHEREWHERE (type = 'json' AND JSON_VALID(content)) OR type != 'json'