循环可以让你把一段代码重复执行好多次,只要满足某个条件,或者遍历某个数据集。这对于自动化任务、处理大量数据或者做重复操作特别有用。
想象一下,你要手动给小组里的每个小孩发糖果。那肯定乱套了!其实你可以遍历小孩名单,依次给每个人发一颗糖。在这个场景里,“遍历名单”就是循环。
PostgreSQL支持几种循环:
LOOP—— 通用循环,一直执行,直到你手动让它停下来。FOR—— 按照数字范围或者查询结果,执行指定次数的循环。WHILE—— 只要条件成立就一直循环。
我们来一个个看下每种循环。
无限循环:LOOP
LOOP是PL/pgSQL里最基础的循环形式,会一直重复执行代码块。这个循环会无限执行,得用EXIT命令手动跳出来。
语法:
LOOP
-- 你的代码写这里
END LOOP;
举个例子。用LOOP算1到10的和:
DO $$
DECLARE
counter INT := 1;
sum INT := 0;
BEGIN
LOOP
sum := sum + counter; -- 加上当前计数器的值
counter := counter + 1; -- 计数器+1
-- 如果计数器大于10就退出循环
IF counter > 10 THEN
EXIT;
END IF;
END LOOP;
RAISE NOTICE '1到10的和: %', sum;
END $$;
- 变量
counter每次循环都会加1。 - 条件
IF counter > 10 THEN EXIT;让计数器超过10时跳出循环。 - 最后输出所有数字的和。
遍历范围或数据集的循环:FOR
第二种循环,FOR,用来遍历:
- 数字范围。
- SQL查询结果。
遍历数字范围的循环
语法:
FOR variable IN [REVERSE] start..end LOOP
-- 你的代码写这里
END LOOP;
输出1到5的数字:
DO $$
BEGIN
FOR i IN 1..5 LOOP
RAISE NOTICE '当前值: %', i;
END LOOP;
END $$;
反向遍历的例子:
DO $$
BEGIN
FOR i IN REVERSE 5..1 LOOP
RAISE NOTICE '反向顺序: %', i;
END LOOP;
END $$;
遍历SQL查询结果的循环
这个方式很适合处理表里的每一行。
语法:
FOR variable IN QUERY (SELECT ...) LOOP
-- 你的代码写这里
END LOOP;
举个遍历students表的例子:
DO $$
DECLARE
student_name TEXT;
BEGIN
FOR student_name IN QUERY (SELECT name FROM students) LOOP
RAISE NOTICE '你好, %!', student_name;
END LOOP;
END $$;
条件循环:WHILE
WHILE会一直执行,直到条件不成立为止。
语法:
WHILE 条件 LOOP
-- 你的代码写这里
END LOOP;
用WHILE算1到10的和:
DO $$
DECLARE
counter INT := 1;
sum INT := 0;
BEGIN
WHILE counter <= 10 LOOP
sum := sum + counter;
counter := counter + 1;
END LOOP;
RAISE NOTICE '1到10的和: %', sum;
END $$;
生活中的例子
现在我们已经搞懂循环的基础了,来看看实际应用的例子。
例子1:生成乘法表
DO $$
DECLARE
i INT;
j INT;
BEGIN
FOR i IN 1..5 LOOP
FOR j IN 1..5 LOOP
RAISE NOTICE '% x % = %', i, j, i * j;
END LOOP;
END LOOP;
END $$;
例子2:遍历查询结果。 假设我们有个products表,字段有id和price。我们把所有价格都涨10%。
DO $$
DECLARE
prod RECORD;
BEGIN
FOR prod IN QUERY (SELECT id, price FROM products) LOOP
UPDATE products
SET price = prod.price * 1.1
WHERE id = prod.id;
END LOOP;
END $$;
常见错误以及怎么避免
在LOOP或WHILE里死循环。 如果你忘了加退出条件(EXIT或者WHILE里的正确条件),循环就永远不会停。就像开车没刹车一样。
遍历查询结果时出错。 如果结果数据结构和你预期的不一样,FOR IN QUERY循环里就可能报错。
循环里写了不高效的查询。 比如每次循环都UPDATE,会让执行速度很慢。这种情况最好用一条SQL语句搞定,不要用循环。
GO TO FULL VERSION