leave必须带显式声明的标签,否则报error 1305;标签需紧贴while前无空行或注释,且必须已用label_name: loop/while/begin定义。

MySQL用LEAVE跳出循环必须加标签
不加标签的LEAVE会直接报错ERROR 1305 (42000): LEAVE with no matching label,因为MySQL要求每个LEAVE必须明确指向一个已命名的代码块。常见错误是只写LEAVE;,或把标签写在WHILE前面隔了空行或注释。
正确写法必须满足三点:
- 标签名紧贴
WHILE前,中间不能有换行或注释,例如my_loop: WHILE i -
LEAVE后必须跟相同标签名,例如LEAVE my_loop; - 如果嵌套多层循环,内层
LEAVE不能省略标签,否则默认跳出最近一层,容易误判
PostgreSQL里EXIT和EXIT WHEN不能混用
PL/pgSQL中EXIT是无条件退出,EXIT WHEN condition是条件退出,二者语法层级不同。写成EXIT WHEN true THEN ...会语法报错;反过来,用IF condition THEN EXIT; END IF;虽然能跑通,但多了一层判断开销,没必要。
更关键的是:如果循环体里有RAISE NOTICE或变量赋值这类纯计算操作,EXIT WHEN依然有效,但statement_timeout对它完全无效——超时机制只管SQL执行,不管PL/pgSQL控制流。
SQL Server中BREAK和RETURN行为差异极大
BREAK只跳出当前WHILE,后续语句照常执行;RETURN则立刻终止整个存储过程,后面所有代码(包括PRINT 'done')都不会运行。
容易踩坑的点:
- 误用
BREAK以为能退出过程,结果后续逻辑继续执行,造成数据不一致 - 在事务块里用
RETURN,但没显式ROLLBACK或COMMIT,导致连接挂着未结束事务 -
CONTINUE跳过本次迭代后,仍会执行循环末尾的SET @i = @i + 1,这点和MySQL的ITERATE不同
所有数据库都绕不开的死循环兜底方案
无论用哪种LEAVE/EXIT/BREAK,只要循环条件依赖外部状态(比如SELECT MAX(id)结果),就可能因并发写入导致永远不满足退出条件。这时候计数器+上限是唯一靠谱手段。
必须做的三件事:
- 声明
DECLARE i INT DEFAULT 0和DECLARE max_iter INT DEFAULT 10000 - 循环条件写成
WHILE i ,不能只靠业务条件 -
SET i = i + 1必须放在循环体最后,且不能被IF包裹——否则异常跳过就会卡死
循环结束后务必查SELECT i, max_iter,如果i == max_iter,说明是被截断的,得翻日志确认业务是否完整跑完。











