
每天分享技术栈,开发工具等
到目前为止,我们只是实现了“查询一个人”这种简单功能。但实际业务中你经常会遇到:
这些就离不开存储过程中的:
变量/ 循环(如
WHILE、FOR)
我们来做一个实际点的例子:
“遍历 users 表,把年龄小于 30 的人都打印出来,并且给他们发个‘系统欢迎消息’。”
模拟这个过程,咱们一步步来。
WHILE)
CREATEDATABASEIFNOTEXISTS test_sp;
USE test_sp;
CREATETABLEIFNOTEXISTS users (
    id INTAUTO_INCREMENTPRIMARYKEY,
    username VARCHAR(50),
    age INT
);
INSERTINTO users (username, age)VALUES
('Alice',25),
('Bob',30),
('Charlie',22),
('Daisy',28),
('Edward',40);
DELIMITER $$
CREATEPROCEDURE loop_young_users()
BEGIN
DECLARE finished INTDEFAULT0;
DECLARE uid INT;
DECLARE uname VARCHAR(50);
DECLARE uage INT;
-- 游标,用来遍历所有年龄小于30的用户
DECLARE user_cursor CURSORFOR
SELECT id, username, age FROM users WHERE age <30;
-- 捕获结束
DECLARE CONTINUEHANDLERFORNOT FOUND SET finished =1;
-- 打开游标
OPEN user_cursor;
-- 开始循环
    read_loop: LOOP
FETCH user_cursor INTO uid, uname, uage;
IF finished =1THEN
LEAVE read_loop;
ENDIF;
-- 模拟“发送消息”
SELECT CONCAT('已向 ', uname,'(年龄:', uage,')发送系统欢迎消息')AS info;
ENDLOOP;
-- 关闭游标
CLOSE user_cursor;
END $$
DELIMITER;
CALL loop_young_users();
输出类似:
+---------------------------------------------+
| info                                        |
+---------------------------------------------+
| 已向 Alice(年龄:25)发送系统欢迎消息       |
| 已向 Charlie(年龄:22)发送系统欢迎消息     |
| 已向 Daisy(年龄:28)发送系统欢迎消息       |
+---------------------------------------------+
FOR循环更简洁)假设你在 psql或 pgAdmin中操作:
CREATETABLEIFNOTEXISTS users (
    id SERIAL PRIMARYKEY,
    username VARCHAR(50),
    age INT
);
INSERTINTO users (username, age)VALUES
('Alice',25),
('Bob',30),
('Charlie',22),
('Daisy',28),
('Edward',40);
CREATE OR REPLACE PROCEDURE loop_young_users()
LANGUAGE plpgsql
AS $$
DECLARE
    rec RECORD;
BEGIN
FOR rec IN SELECT id, username, age FROM users WHERE age <30LOOP
        RAISE NOTICE '已向 %(年龄:%)发送系统欢迎消息', rec.username, rec.age;
END LOOP;
END;
$$;
CALL loop_young_users();
输出(PostgreSQL 在终端或日志中显示 NOTICE):
NOTICE:  已向 Alice(年龄:25)发送系统欢迎消息
NOTICE:  已向 Charlie(年龄:22)发送系统欢迎消息
NOTICE:  已向 Daisy(年龄:28)发送系统欢迎消息
| 功能 | MySQL 写法 | PostgreSQL 写法 | 
|---|---|---|
| 过程创建 | CREATE PROCEDURE | CREATE PROCEDURE ... LANGUAGE plpgsql | 
| 循环 | LOOP + FETCH + 游标 | FOR record IN SELECT(更简单) | 
| 输出信息 | SELECT '...' | RAISE NOTICE | 
| 游标 | 显式声明 + 打开/关闭 | 可以不用游标,直接用 FOR |