高频分支必须前置,null判断必须显式,复杂计算不可塞入条件;if/case按序求值且短路,高命中率分支置顶可提升性能;case适用于表达式场景,if适用于多语句控制流。

高频分支必须前置,NULL判断必须显式,复杂计算不能塞进条件里——否则性能和语义都会出问题。
IF分支顺序为什么直接影响执行效率
SQL Server、PostgreSQL、MySQL 都严格按书写顺序逐个求值 IF 或 CASE WHEN 条件,遇到第一个为真就终止。这意味着:95% 是 @status = 'published',但它写在第二位,每次调用都要先执行一次无谓的 @status = 'draft' 判断。
- 把统计上命中率最高的分支放在最前面,不是按字母序,也不是按业务流程图顺序
- 避免在条件中写
ISNULL(@input, '') != ''这类隐式转换——改用@input IS NOT NULL AND @input != '',既支持短路,又明确语义 - 如果某个
WHEN里写了(SELECT COUNT(*) FROM huge_log WHERE ...),而它命中率仅 0.1%,那 99.9% 的调用都在白跑全表扫描
什么时候该用CASE替代IF嵌套
CASE 是表达式,IF 是控制流语句。别用 IF 去干 CASE 的活——比如只是根据字段值返回不同字符串、做分级打标、状态转义。
- 适用场景:
SELECT中的状态映射、WHERE中的简单等值路由(但注意索引失效风险)、函数参数计算 - 不适用场景:需要
RETURN、INSERT、UPDATE等多行执行逻辑时,CASE无法替代IF -
CASE所有分支必须返回兼容类型;没写ELSE且无匹配时返回NULL,线上容易埋空值坑 - 错误示范:
WHERE col = CASE @flag WHEN 1 THEN 'A' WHEN 2 THEN 'B' END——这会让优化器放弃使用col上的索引
MySQL中IF-ELSEIF对NULL的三值逻辑陷阱
MySQL 不会把 NULL = 'user' 当作假,而是返回 UNKNOWN,导致整个 IF 链直接掉进 ELSE。如果你本意是“NULL 算默认值”,结果却触发了低效兜底逻辑(比如查配置表),问题就藏得很深。
- 高频默认分支必须显式包含
IS NULL判断,例如:IF @type IS NULL OR @type = 'user' - 不要依赖
ELSE当兜底——它永远最后执行,一旦高频路径被误归入其中,等于主动放弃优化机会 - 多个变量联合判断时(如
@status = 'active' AND @tenant_id IS NOT NULL),任一为NULL整个条件即为UNKNOWN,务必拆开检查
嵌套过深时如何降低维护成本
三层以上 IF 嵌套不是语法错误,而是可维护性红灯。你改一个条件,要翻页找括号配对、担心漏掉 END IF、难定位哪段逻辑真正生效。
- 优先把纯值映射类逻辑抽成
CASE表达式,写在SELECT或变量赋值里,而非控制流中 - 对重复出现的复合条件(如
v_BillStatus='7' AND v_status='1' AND v_Userid = v_courierUserId),提前用DECLARE变量缓存布尔结果,避免重复计算 - 避免“条件驱动执行”变成“硬编码驱动执行”:比如用
IF @action IN ('create', 'update', 'delete')替代平铺三个IF,再配合动态 SQL 或预编译分支处理
真正难的不是写对分支,而是让后续接手的人一眼看出哪个分支最常走、哪个条件最容易为空、哪个子查询其实可以提前剪枝——这些细节全靠顺序、显式判断和表达式拆分来暴露。










