news 2026/10/8 8:06:22

postgresql存储过程如何写

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
postgresql存储过程如何写

在 PostgreSQL 里,其实 99% 场景你写的是 函数(FUNCTION);

真正的 存储过程(PROCEDURE) 是 11 版才引入,语法几乎一样,只是调用方式不同。

下面把“函数”和“过程”都给你一次讲透,并附完整可直接 `psql -f` 运行的脚本。

---

一、先分清:FUNCTION vs PROCEDURE

特性 FUNCTION PROCEDURE
最早版本 一直就有 ≥ 11
能否回传结果集 ✅ `RETURNS TABLE / SETOF` ❌(只能 OUT 参数)
调用方式 `SELECT func(args);` `CALL proc(args);`
能否无返回值 ❌ 必须有 `RETURNS` ✅ 可以啥都不返回
事务控制 由外层决定 内部可 `COMMIT/ROLLBACK`

结论:
- 只要你想“查”数据 → 写 FUNCTION;
- 只要你想“干”事且内部自己提交 → 写 PROCEDURE。

---

二、FUNCTION 模板(最常用)

```sql
-- 返回单行
CREATE OR REPLACE FUNCTION get_user_name(uid bigint)
RETURNS text
LANGUAGE plpgsql
AS $$
DECLARE
v_name text;
BEGIN
SELECT name INTO v_name
FROM users
WHERE id = uid;
RETURN v_name; -- 找不到会返回 NULL
END;
$$;

-- 返回结果集
CREATE OR REPLACE FUNCTION list_users(min_age int)
RETURNS TABLE(id bigint, name text, age int)
LANGUAGE plpgsql
AS $$
BEGIN
RETURN QUERY
SELECT u.id, u.name, u.age
FROM users u
WHERE u.age >= min_age
ORDER BY u.age;
END;
$$;

-- 测试
SELECT get_user_name(1);
SELECT * FROM list_users(18);
```

---

三、PROCEDURE 模板(≥ pg11)

```sql
-- 内部自己提交,外部自动回滚不了
CREATE OR REPLACE PROCEDURE transfer_money(
from_id bigint,
to_id bigint,
amount numeric
)
LANGUAGE plpgsql
AS $$
BEGIN
-- 扣钱
UPDATE accounts SET balance = balance - amount WHERE id = from_id;
-- 加钱
UPDATE accounts SET balance = balance + amount WHERE id = to_id;
-- 记日志
INSERT INTO log(from_acc, to_acc, amt, ts)
VALUES (from_id, to_id, amount, now());
-- 手动提交(函数里不允许)
COMMIT;
END;
$$;

-- 调用
CALL transfer_money(3, 5, 100.00);
```

---

四、参数 5 种写法速查
1. `IN` 默认,只进不出
2. `OUT` 只出不进
3. `INOUT` 能进能出
4. `VARIADIC` 可变长参数
5. 缺省值 `age int DEFAULT 18`

示例(INOUT):

```sql
CREATE OR REPLACE FUNCTION swap(INOUT a int, INOUT b int)
LANGUAGE plpgsql AS $$
DECLARE tmp int;
BEGIN
tmp := a; a := b; b := tmp;
END;
$$;

-- 调用
SELECT swap(3,7); -- 返回 7,3
```

---

五、异常处理模板

```sql
CREATE OR REPLACE FUNCTION safe_divide(a numeric, b numeric)
RETURNS numeric
LANGUAGE plpgsql
AS $$
BEGIN
RETURN a / b;
EXCEPTION
WHEN division_by_zero THEN
RAISE NOTICE '除零,返回 NULL';
RETURN NULL;
WHEN OTHERS THEN
RAISE WARNING '未知错误: %', SQLERRM;
RETURN NULL;
END;
$$;
```

---

六、快速验证脚本
把下面内容存成 `proc.sql`,然后

`psql -U postgres -d yourdb -f proc.sql` 即可一键验证。

```sql
-- 建测试表
DROP TABLE IF EXISTS users;
CREATE TABLE users(
id bigserial PRIMARY KEY,
name text NOT NULL,
age int CHECK (age>0)
);

-- 灌点数据
INSERT INTO users(name,age) VALUES
('Alice',19),('Bob',25),('Carol',30);

-- 函数:返回结果集
CREATE OR REPLACE FUNCTION list_users(min_age int)
RETURNS TABLE(id bigint, name text, age int)
LANGUAGE plpgsql AS $$
BEGIN
RETURN QUERY SELECT u.id, u.name, u.age FROM users u WHERE u.age >= min_age;
END;
$$;

-- 过程:无结果,内部可 COMMIT
CREATE OR REPLACE PROCEDURE add_user(p_name text, p_age int)
LANGUAGE plpgsql AS $$
BEGIN
INSERT INTO users(name,age) VALUES (p_name, p_age);
COMMIT;
END;
$$;

-- 测试
SELECT * FROM list_users(20); -- 函数
CALL add_user('David', 40); -- 过程
SELECT * FROM list_users(20);
```

---

七、小结口诀
- 要查询 → `FUNCTION` + `RETURNS`/`TABLE`
- 要干活 → `PROCEDURE` + `CALL`(≥11)
- 想回传单个值 → `OUT` 参数
- 想回传结果集 → `RETURN QUERY`

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 2:39:50

PyTorch-CUDA-v2.7镜像中设计A/B测试验证新功能有效性

PyTorch-CUDA-v2.7镜像中设计A/B测试验证新功能有效性 在现代AI研发体系中,一个看似微小的模型改动——比如更换激活函数、调整优化器参数,甚至只是升级了框架版本——都可能对最终性能产生深远影响。然而,如何科学地判断这种“改进”是否真的…

作者头像 李华
网站建设 2026/10/6 11:45:53

PyTorch-CUDA-v2.7镜像中提供uptime监控页面展示服务状态

PyTorch-CUDA-v2.7 镜像中的 Uptime 监控:让 AI 开发环境“看得见” 在深度学习项目中,最怕的不是模型不收敛,而是你半夜醒来发现训练任务早已静默崩溃——没有日志、没有告警,只有空荡荡的终端和丢失的一周算力。更糟的是&#x…

作者头像 李华
网站建设 2026/10/6 4:16:49

PyTorch-CUDA-v2.7镜像资源限制设置:CPU和内存配额分配

PyTorch-CUDA-v2.7镜像资源限制设置:CPU和内存配额分配 在现代AI开发环境中,你是否曾遇到这样的场景:团队成员在同一台GPU服务器上运行任务,突然某个训练进程“吃光”了所有CPU和内存,导致整个系统卡顿甚至崩溃&#x…

作者头像 李华
网站建设 2026/10/6 5:18:01

PyTorch-CUDA-v2.7镜像中备份数据库的自动化脚本编写

PyTorch-CUDA-v2.7镜像中备份数据库的自动化脚本编写 在现代AI平台日益复杂的运维场景下,一个常被忽视的问题浮出水面:我们投入大量资源优化模型训练速度和GPU利用率,却往往忽略了支撑这些实验的“幕后英雄”——数据库。无论是存储超参数配置…

作者头像 李华
网站建设 2026/10/6 13:16:11

PyTorch-CUDA-v2.7镜像中接入WebSocket实现实时监控推送

PyTorch-CUDA-v2.7镜像中接入WebSocket实现实时监控推送 在现代AI研发实践中,一个常见的痛点是:你启动了模型训练任务,然后只能盯着日志文件或等待TensorBoard刷新——整个过程就像在“盲跑”。尤其当训练周期长达数小时甚至数天时&#xff0…

作者头像 李华
网站建设 2026/10/6 21:22:04

PyTorch-CUDA-v2.7镜像中启用TensorBoard可视化工具

PyTorch-CUDA-v2.7镜像中启用TensorBoard可视化工具 在深度学习项目开发过程中,模型训练早已不再是单纯的“跑通代码”那么简单。随着网络结构日益复杂、数据规模不断增长,开发者面临的挑战也从“能不能训出来”转向了“为什么训得不好”。此时&#xff…

作者头像 李华