痛点

病害的”共有 / 复合”状态算完得持久化。几百上千条病害,最开始是逐条 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/批),速度和一致性都好不少。