痛点

病害的“共有 / 复合”状态计算完要持久化。几百上千条病害,最初是逐条 UPDATE,两个问题:一是慢,每次 UPDATE 都是一次磁盘事务;二是没整体事务保护,中途失败会留下半新半旧的数据。

CASE WHEN 批量更新

把 N 条逐条 UPDATE 合成一条,用 CASE WHEN 给每行不同的值:

UPDATE defect
SET compound_level = CASE id
WHEN 101 THEN 'AA'
WHEN 102 THEN 'A1'
WHEN 103 THEN 'B'
END,
is_compound = CASE id
WHEN 101 THEN 1
WHEN 102 THEN 1
WHEN 103 THEN 0
END
WHERE id IN (101, 102, 103)

一次往返更新多行多列,磁盘事务次数从 N 次降到 1 次。配合 TransactionTemplate 包一层,要么全成功要么全回滚。

SQLite 的 999 变量上限

这里有个 SQLite 的坑:单条 SQL 的绑定变量数有上限,默认 999(新版可配到 32766)。CASE WHEN 里每个 WHEN x THEN y 都算变量,列数 × 行数很容易超。

所以要按批切分。规则很简单:

单批最大行数 = floor(999 / 每行变量数)

比如每行 7 个变量字段,单批最多 999/7 ≈ 142 行,留点余量取 100 行 / 批;复合病害字段更多就 70 行 / 批。超出就分多次执行,每次都包在事务里。

小结

大批量更新的标准套路:CASE WHEN 合并 + 事务包裹 + 按变量上限分批。DB 交互次数从 O(N) 降到 O(N/批),速度和一致性都上一个台阶。