当你在PostgreSQL里写函数时,第一个要搞明白的事就是怎么返回结果。有时候你只需要返回一个数字,有时候要返回一整张表,有时候甚至要返回好几个数据集。这一节我们把所有常见的方式都过一遍:从最简单的RETURN到RETURN QUERY、RETURNS TABLE和SETOF。
单个结果:RETURN
如果你的函数只需要返回一个值——比如总数或者行数——那就用普通的RETURN就行。
CREATE FUNCTION count_students() RETURNS INT AS $$
DECLARE
total INT;
BEGIN
SELECT COUNT(*) INTO total FROM students;
RETURN total;
END;
$$ LANGUAGE plpgsql;
当你在PL/pgSQL里创建函数时,必须指定它返回什么类型。这就是RETURNS关键字的作用,它决定了函数返回结果的“格式”。所以你想返回一个数字、文本还是一张表,都要在RETURNS那一行写清楚。
简单例子:
CREATE FUNCTION add_numbers(a INT, b INT) RETURNS INT AS $$
BEGIN
RETURN a + b;
END;
$$ LANGUAGE plpgsql;
这里的RETURNS INT意思就是这个函数会返回一个数字。
返回单个值
我们先从最简单的来——写一个函数,返回一个值。比如,统计students表里学生数量的函数:
CREATE FUNCTION count_students() RETURNS INT AS $$
DECLARE
total INT;
BEGIN
SELECT COUNT(*) INTO total FROM students; -- 把查询结果存到total变量里
RETURN total; -- 返回结果
END;
$$ LANGUAGE plpgsql;
现在你可以这样调用这个函数:
SELECT count_students(); -- 会返回学生数量
用RETURNS TABLE返回多行数据
有时候你不只想返回一个值,而是要返回一堆记录。比如,返回所有学生的id和名字列表。这时候就要用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(); -- 会返回所有学生的表格
注意RETURNS TABLE关键字。它说明这个函数会返回一个有指定字段(这里是id和name)的表。
用RETURN QUERY
你应该已经喜欢上上面的例子了。但还有个细节:RETURN QUERY是PL/pgSQL里的魔法棒,可以直接把查询结果返回。用它你可以返回整个查询的结果,也可以只返回一部分。
比如,我们要返回所有状态为active = TRUE的学生:
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;
现在你可以调用这个函数,拿到所有活跃学生的数据:
SELECT * FROM get_active_students();
不用RETURNS TABLE返回多行
有时候你可能想返回多行数据,但又不想用RETURNS TABLE。这时候可以用SETOF类型。它允许你返回结构一样的多行数据。 比如:
CREATE FUNCTION get_student_names() RETURNS SETOF TEXT AS $$
BEGIN
RETURN QUERY
SELECT name
FROM students;
END;
$$ LANGUAGE plpgsql;
这个函数只会返回学生名字的列表:
SELECT * FROM get_student_names();
根据输入参数返回不同的值
函数不一定只返回静态结果。它们可以用参数动态改变返回内容。
比如,按学生id返回数据的例子:
CREATE FUNCTION get_student_by_id(student_id INT) RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
RETURN QUERY
SELECT id, name
FROM students
WHERE id = student_id; -- 用student_id参数
END;
$$ LANGUAGE plpgsql;
现在你可以查某个学生的信息:
SELECT * FROM get_student_by_id(3); -- 会返回ID=3的学生数据
返回复杂数据(多个数据集)
有时候数据太复杂,需要分几组返回。这时候可以用游标。比如,你想从一个函数里返回两个数据集——活跃学生和不活跃学生的列表。
CREATE FUNCTION get_students_status() RETURNS SETOF RECORD AS $$
BEGIN
RETURN QUERY
SELECT id, name, 'active' AS status
FROM students
WHERE active = TRUE;
RETURN QUERY
SELECT id, name, 'inactive' AS status
FROM students
WHERE active = FALSE;
END;
$$ LANGUAGE plpgsql;
现在你可以拿到这两组数据:
SELECT * FROM get_students_status();
用RETURNS时常见的坑
没写返回类型: 如果你没写函数返回什么类型,PostgreSQL会报错。比如:
CREATE FUNCTION no_return_type() AS $$ -- 错误,没写RETURNS
BEGIN
RETURN 1;
END;
$$ LANGUAGE plpgsql;
数据类型不匹配: 要保证你返回的值和声明的类型一致。比如你写了INT,就别返回字符串。
忘了用RETURN QUERY: 如果你忘了在复杂查询里用RETURN QUERY,函数啥都不会返回。
多值返回写错: 如果你想返回多行数据,但没用SETOF或TABLE,PostgreSQL也会报错。
GO TO FULL VERSION