简单CASE仅支持等值比较,语法为CASE expression WHEN value THEN result,WHEN后不可用运算符、函数或NULL;搜索CASE(CASE WHEN condition THEN result)支持任意布尔表达式,更灵活安全,是项目主力写法。

简单CASE只能做等值比较,不能写运算符
简单CASE的语法是 CASE expression WHEN value THEN result,它内部隐含的是 = 比较逻辑。这意味着你无法在 WHEN 后面写 >、BETWEEN、LIKE 或函数调用——哪怕只是加个空格或 trim 都会报错。
常见错误现象:
-
CASE status WHEN TRIM('pending') THEN '待处理'→ 报错,因为TRIM()不被允许出现在简单CASE的WHEN值位置 -
CASE age WHEN NULL THEN '未知'→ 永远不匹配,简单CASE对NULL值不做特殊处理,expression = NULL结果恒为UNKNOWN,直接跳到ELSE -
CASE score WHEN 90 THEN 'A' WHEN 95 THEN 'S'→ 如果score是92.5,不会进任何分支,即使你本意是想覆盖区间
搜索CASE支持任意布尔表达式,是实际项目的主力写法
搜索CASE即 CASE WHEN condition THEN result 形式,每个 WHEN 后是一个完整可执行的布尔表达式。它能覆盖简单CASE所有能力,且更灵活、更易读、更少隐式陷阱。
使用场景和实操建议:
- 需要范围判断(如
score >= 90)、模糊匹配(name LIKE '%test%')、空值检查(col IS NULL)时,必须用搜索CASE - 多个条件共用同一字段时,避免重复写字段名:写
CASE WHEN x > 10 AND x 比反复写 <code>CASE x WHEN 11 THEN ... WHEN 12 THEN ...更安全 - 注意短路特性:条件顺序影响结果,比如
WHEN x > 50 THEN '高' WHEN x > 10 THEN '中'是对的;反过来就会让所有 >50 的值都进第二分支
类型兼容性要求两者一致,但错误表现不同
无论是简单还是搜索CASE,所有 THEN 和 ELSE 分支返回的值必须能隐式转换为同一类型。否则 PostgreSQL 会直接报错,比如 ERROR: column "x" has type integer but expression has type text。
容易踩的坑:
- 简单CASE中,
expression和每个WHEN value类型必须严格兼容(例如都是TEXT或都能转成INTEGER),不支持跨类型自动推导 - 搜索CASE中,各
THEN的类型冲突更容易暴露:比如WHEN flag THEN 'yes' ELSE 0会失败,因为'yes'是TEXT,0是INTEGER,没有公共类型 - 省略
ELSE时,所有分支都不满足会返回NULL,但该NULL的数据类型由其他分支推导——若无分支,类型推导失败,语句直接报错
UPDATE/SELECT/GROUP BY 中的 CASE 行为完全一致,但聚合上下文要特别小心
CASE 在 SELECT、UPDATE、WHERE、ORDER BY 甚至 HAVING 中行为统一,但嵌套在聚合函数里时,逻辑容易混淆。
关键点:
- 在
UPDATE中用搜索CASE实现分条件更新是标准做法,比如SET price = CASE WHEN qty > 100 THEN price * 0.9 ELSE price END - 在
GROUP BY或聚合中写CASE时,它本身不触发分组,只是为每行生成一个临时分类值,再配合SUM(CASE ...)实现“条件计数”或“行列转换” - 不能在同一个
SELECT中混用聚合与非聚合的CASE引用:比如CASE WHEN amount > AVG(amount) THEN ...是非法的,必须把AVG(amount)提前用子查询算出
真正麻烦的不是语法选择,而是当业务规则变复杂后,简单CASE会逼你把逻辑硬拆成一堆离散值枚举,而搜索CASE只要改条件就能延展——但很多人一开始图省事写简单CASE,后来发现字段加了新状态、范围边界调整、还要兼容空值,就只能重写。

















