在PostgreSQL里,函数是个超强工具,可以帮你自动化任务、写业务逻辑,让服务器变得更聪明。你可以把函数想象成数据库里的小程序。它们很适合:
- 代码复用。如果你老是写一样的查询,把它们包进函数里,想用就直接调。
- 自动化任务。比如你要根据员工工时算工资,用函数就很方便。
- 封装逻辑。把复杂的计算都放到服务器端,客户端不用再纠结SQL怎么写。
CREATE FUNCTION的基本语法
函数的基本结构长这样:
CREATE FUNCTION function_name(parameters) RETURNS return_type AS $$
BEGIN
-- 函数体(逻辑)
RETURN 结果;
END;
$$ LANGUAGE plpgsql;
来拆解一下主要部分:
CREATE FUNCTION function_name(parameters):
这行是给函数起名字function_name,还可以加参数(如果需要的话)。
参数可以写名字和类型:my_param INTEGER,another_param TEXT。
RETURNS return_type:
这里写函数要返回啥:一个值(INTEGER、TEXT啥的)或者一堆数据(TABLE、RECORD)。
BEGIN ... END:
这俩关键词中间就是“函数体”,所有操作都在这儿写。
RETURN 结果:
返回函数执行的结果。注意:返回值类型要和RETURNS里写的一样。
LANGUAGE plpgsql:
这里指定用PL/pgSQL语言。PostgreSQL还支持别的语言,但我们现在就用这个。
简单例子:两个数相加
来写个函数,返回两个整数的和。
CREATE FUNCTION add_numbers(a INT, b INT) RETURNS INT AS $$
BEGIN
RETURN a + b;
END;
$$ LANGUAGE plpgsql;
现在来调用一下:
SELECT add_numbers(5, 7); -- 结果:12
发生了啥?
- 函数接收两个参数
a和b,类型都是INT。 - 函数体里直接把它们加起来(
a + b),然后返回。 - 就像个计算器一样简单!
用变量的例子
假设我们有个大学的数据库,想知道有多少学生注册了。
写个函数:
CREATE FUNCTION count_students() RETURNS INT AS $$
DECLARE
total INT; -- 声明个变量存结果
BEGIN
SELECT COUNT(*) INTO total FROM students; -- 统计表里有多少行
RETURN total; -- 返回结果
END;
$$ LANGUAGE plpgsql;
调用函数:
SELECT count_students(); -- 假设结果:120
这里我们看到:
- 用变量
total来存SQL查询的结果。 SELECT ... INTO语句把查询结果塞进变量里。
这种写法很适合你要先处理下数据再返回的场景。
返回多个值:RETURNS TABLE
上面例子只返回了一个值。如果你想让函数返回一堆数据,比如学生列表,就要用RETURNS TABLE。
例子:
CREATE FUNCTION get_students() RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
RETURN QUERY SELECT id, name FROM students;
END;
$$ LANGUAGE plpgsql;
调用函数:
SELECT * FROM get_students();
可能的结果:
| id | name |
|---|---|
| 1 | Alice |
| 2 | Bob |
| 3 | Charlie |
RETURN QUERY的好处:直接在函数里查数据
RETURN QUERY让你可以直接把SQL查询的结果返回出去,省了中间变量,函数更简洁。
写个函数,只返回活跃的学生:
CREATE FUNCTION get_active_students() RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
RETURN QUERY SELECT id, name FROM students WHERE active = TRUE;
END;
$$ LANGUAGE plpgsql;
在调用get_active_students()前,得先建个students表并插点测试数据。可以这样:
-- 创建学生表
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
active BOOLEAN DEFAULT TRUE
);
-- 插入几条记录
INSERT INTO students (name, active) VALUES
('Alice', FALSE),
('Bob', TRUE),
('Charlie', TRUE),
('Dana', FALSE);
表格:
| id | name | active |
|---|---|---|
| 1 | Alice | false |
| 2 | Bob | true |
| 3 | Charlie | true |
| 4 | Dana | false |
现在调用:
SELECT * FROM get_active_students();
结果:
| id | name |
|---|---|
| 2 | Bob |
| 3 | Charlie |
执行前校验数据的正确性
函数里可以用IF判断,保证数据没问题。比如,只有学生所有考试都过了,才能升到下一级。
例子:
CREATE FUNCTION promote_student(student_id INT) RETURNS TEXT AS $$
DECLARE
passed_exams INT;
BEGIN
-- 统计学生通过的考试数量
SELECT COUNT(*) INTO passed_exams
FROM exams
WHERE student_id = promote_student.student_id AND status = '通过';
-- 判断条件
IF passed_exams < 5 THEN
RETURN '学生通过的考试不够';
END IF;
-- 更新学生年级
UPDATE students
SET course = course + 1
WHERE id = promote_student.student_id;
RETURN '学生已升级!';
END;
$$ LANGUAGE plpgsql;
写函数时常见的坑
没写返回值类型。PostgreSQL要求你必须写清楚函数返回啥。比如:
CREATE FUNCTION fail() AS $$ -- 错误:没写RETURNS
BEGIN
RETURN 1;
END;
$$ LANGUAGE plpgsql;
修正:
CREATE FUNCTION succeed() RETURNS INT AS $$
BEGIN
RETURN 1;
END;
$$ LANGUAGE plpgsql;
返回值类型不对。你写了RETURNS INT,就得返回数字。要是返回字符串就不行。
函数里的SQL写错了。用函数前一定要先单独测试下SQL,最好在psql或pgAdmin里手动跑一遍。
GO TO FULL VERSION