pl/pgsql中for record in query是最安全的集合遍历方式,自动管理游标且需在begin...end内使用;数值型for适用于固定范围迭代;while适合动态终止条件;嵌套循环需警惕性能问题。

PL/pgSQL 中 FOR record IN query 是最常用且安全的集合遍历方式
直接用 FOR 遍历查询结果集,是处理表数据最自然的方式。它自动声明游标、隐式打开/关闭,出错时也比手动游标更易排查。
- 必须在
BEGIN ... END块内使用,不能在匿名块外单独写 -
record是隐式声明的行变量,类型由SELECT列表决定;访问字段用点号,如record_data.id - 如果查询返回 0 行,循环体一次都不执行,不会报错
- 避免在循环体内修改正在遍历的同一张表(除非加锁或用快照),否则可能漏行或重复处理
需要控制迭代次数或范围?优先用 FOR i IN start..end 数值循环
当你要生成序列、补全日期、批量插入编号等场景,数值型 FOR 比拼字符串再转整更可靠,也比 WHILE 少写三行控制逻辑。
- 默认升序;降序必须显式加
REVERSE,例如FOR i IN REVERSE 10..1 - 步长固定为 1,不支持
STEP 2这类语法;如需跳步,改用WHILE或在循环体内判断 - 注意边界:若
start > end且未加REVERSE,循环直接跳过,不报错也不警告 - 数值过大(比如
1..1000000)会实际分配内存并迭代,可能卡住;大数据量建议分页或用集合操作替代
WHILE 循环适合动态终止条件,但容易陷入无限循环
当你无法预知循环次数,比如要持续拉取队列任务直到为空,或根据某字段聚合状态决定是否继续,WHILE 更灵活。
- 条件判断在每次循环**前**执行,所以空集时循环体不会运行
- 必须确保循环体内有能改变条件变量的语句,否则立刻死循环;常见错误是忘了更新计数器或没
EXIT判断 - 推荐搭配
EXIT WHEN condition提前退出,比把所有逻辑塞进WHILE条件里更清晰 - 不要在
WHILE内反复执行相同SELECT COUNT(*)判断是否结束——先查一次存变量,再用变量驱动
嵌套循环性能敏感,务必检查执行计划和索引
两层 FOR(比如部门 × 日期)在生成测试数据时很常见,但上线后可能变成慢查询源头。
- 外层每迭代一次,内层查询都重新执行;如果内层是
SELECT * FROM large_table,复杂度是 O(n×m) - 用
EXPLAIN ANALYZE看实际执行计划,确认内层查询是否走了索引;没索引时,考虑提前物化中间结果到临时表 - 避免在嵌套循环里做
INSERT ... SELECT这类高开销操作;可先收集所有待插数据到数组,最后批量INSERT INTO ... SELECT UNNEST(...) - 临时表名别用
temp_table这种静态名——多个并发调用会冲突,改用pg_temp.mydata_||pg_backend_pid()
真实项目里,循环本身不是瓶颈,瓶颈往往藏在循环体内的 SQL 质量、事务粒度和锁竞争里。写完先跑几条数据看日志,再压测,比盯着语法对错重要得多。











