有时候循环一切都很顺利——直到突然有个理由让你想提前停下来。还好,PL/pgSQL给了我们很方便的工具来搞定这事。
用EXIT中断循环
有时候你需要让循环提前结束,而不是等它自己跑到头。比如说找到了想要的值、发现了错误,或者根据某个条件决定不再继续。这种情况下我们就用EXIT。
EXIT就是跟循环说:“行了,你该干的都干了,可以停了”。
EXIT的语法超级简单:
EXIT WHEN 条件;
这里关键字WHEN指定了在什么条件下循环会被终止。如果你没写条件,EXIT就会直接马上结束当前循环。
例子:找到指定值就结束循环
假设我们有一列学生编号,现在想找出ID等于某个值的学生。一旦找到了,就要结束循环。
DO $$
DECLARE
student_id INT;
BEGIN
FOR student_id IN 1..100 LOOP
RAISE NOTICE '正在检查学生ID: %', student_id;
-- 如果找到了目标学生,就结束循环
IF student_id = 42 THEN
RAISE NOTICE '找到了ID为42的学生!';
EXIT;
END IF;
END LOOP;
END $$;
在这个例子里,循环会遍历1到100的数字,检查每个“学生”。只要ID等于42,就会输出消息然后结束循环。
用CONTINUE跳过某次迭代
有时候你想在循环里跳过某些迭代,但又想让循环继续跑下去。比如你想忽略掉“不需要”的数据,或者针对某些特殊条件跳过处理。
CONTINUE的意思就是:“这个条件不合适,直接进入下一轮吧”。
CONTINUE和EXIT很像,只不过它不是结束整个循环,而是跳过当前这次:
CONTINUE WHEN 条件;
只要条件成立,这次迭代就会被跳过,直接进入下一轮。
例子:跳过偶数
这个例子里我们遍历1到10的数字,但会跳过偶数,只输出奇数。
DO $$
DECLARE
num INT;
BEGIN
FOR num IN 1..10 LOOP
-- 跳过偶数
IF num % 2 = 0 THEN
CONTINUE;
END IF;
RAISE NOTICE '奇数: %', num;
END LOOP;
END $$;
这里CONTINUE会跳过所有num % 2 = 0(也就是偶数)的迭代。结果就是日志里只会输出奇数。
组合使用EXIT和CONTINUE
EXIT和CONTINUE可以一起用,让你更灵活地控制循环。比如你可以用CONTINUE跳过不需要的迭代,但一旦遇到重要的东西就用EXIT结束循环。
比如下面这个例子,我们会跳过所有能被3整除的数字,但只要遇到15就结束循环。
DO $$
DECLARE
num INT;
BEGIN
FOR num IN 1..20 LOOP
-- 跳过能被3整除的数字
IF num % 3 = 0 THEN
CONTINUE;
END IF;
-- 如果数字等于15就结束循环
IF num = 15 THEN
RAISE NOTICE '停在数字 %', num;
EXIT;
END IF;
RAISE NOTICE '当前数字: %', num;
END LOOP;
END $$;
这个循环的逻辑是:
- 能被3整除的数字会被跳过(
CONTINUE)。 - 如果数字等于15,循环就会结束(
EXIT)。 - 其他数字都会被输出。
进阶例子:跳过无效数据,遇到严重错误就终止
现在来点更实际的。假设我们要处理一个学生列表,检查他们的数据。无效的记录要跳过,遇到“严重错误”就直接终止处理。
DO $$
DECLARE
student RECORD;
BEGIN
FOR student IN
SELECT * FROM students
LOOP
-- 跳过数据有问题的记录
IF student.name IS NULL THEN
RAISE NOTICE '跳过ID为 % 的学生: 缺少姓名', student.id;
CONTINUE;
END IF;
-- 遇到严重错误就终止循环
IF student.status = 'ERROR' THEN
RAISE EXCEPTION '学生ID为 % 出现严重错误', student.id;
EXIT; -- 其实这行多余了,因为RAISE EXCEPTION会直接终止执行。
END IF;
-- 处理记录
RAISE NOTICE '正在处理学生: %', student.name;
END LOOP;
END $$;
在这个例子里,CONTINUE用来跳过没有名字的学生,EXIT(配合RAISE EXCEPTION)在遇到严重错误时终止循环。
实用建议和常见错误
别忘了条件逻辑。 在EXIT WHEN或CONTINUE WHEN里条件写错了,可能会导致循环提前结束或者漏掉重要数据。
别滥用CONTINUE。 如果你的代码里CONTINUE太多,可能需要重新考虑一下循环的逻辑,让它更简单点。
别把EXIT和RETURN搞混。 EXIT只会结束当前循环,而RETURN会直接结束整个函数的执行。
小心死循环。 如果你用LOOP循环但没有写好终止条件,又忘了加EXIT,那循环可能会一直跑下去停不下来。
GO TO FULL VERSION