CodeGym /课程 /SQL SELF /RAISE NOTICE, RETURN QUERY 操作符

RAISE NOTICE, RETURN QUERY 操作符

SQL SELF
第 50 级, 课程 3
可用

写代码的时候有两件事特别重要:一是搞清楚到底发生了啥(尤其是当一切都不按你想的来时),二是能返回有用的数据。PL/pgSQL 里这点尤其明显,因为代码跑在服务器端,debug 起来没那么直观。这时候内置工具就很有用了:

RAISE NOTICE —— 这就是在函数执行时输出消息的方式。你可以把它当成 JavaScript 里的 console.log 或 Python 里的 print。你可以输出变量的值、当前执行状态,甚至给未来的自己留个“打招呼”。

RETURN QUERY —— 这是返回一组数据的方法,比如一整张表或者复杂查询的结果。有了它,PL/pgSQL 的函数就像 SQL 查询一样强大。

RAISE NOTICE 命令

RAISE NOTICE 允许你在函数执行过程中把消息输出到屏幕。格式长这样:

RAISE NOTICE '消息: %', 值;
  • % —— 这是变量的占位符,和 C 里的 printf 差不多。
  • 在消息文本后面可以列出你想插进去的变量。

使用示例

假设你写了个函数,要统计不同小组里的学生数量。你想看到中间结果,确认一切都在你的掌控中。

CREATE OR REPLACE FUNCTION count_students_in_groups() RETURNS VOID AS $$
DECLARE
    group_name TEXT;
    student_count INT;
BEGIN
    FOR group_name IN SELECT DISTINCT group_name FROM students LOOP
        SELECT COUNT(*) INTO student_count
        FROM students WHERE group_name = group_name;

        -- 输出结果
        RAISE NOTICE '小组: %, 学生数量: %', group_name, student_count;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

当你调用这个函数时:

SELECT count_students_in_groups();

你会在日志里看到类似这样的消息:

NOTICE:  小组: 数学, 学生数量: 30
NOTICE:  小组: 哲学, 学生数量: 25
NOTICE:  小组: 生物, 学生数量: 18

注意,这个函数啥都不返回(它是 RETURNS VOID),但 RAISE NOTICE 能让你看到循环的进度。

RAISE 的一些小技巧

除了 NOTICE,你还可以用其他消息级别:

  • RAISE DEBUG —— 输出更多细节(只有日志级别设成 DEBUG 时才显示)。
  • RAISE INFO —— 一般信息。
  • RAISE WARNING —— 警告。
  • RAISE EXCEPTION —— 抛出错误,这个我们后面会讲。

调试时最好用 NOTICE 或 DEBUG,因为它们不会中断函数执行,还挺方便的。

RETURN QUERY 命令:像大佬一样返回数据

RETURN QUERY 在 PL/pgSQL 里用来返回多行数据。你可以直接把 SQL 查询的结果从函数里返回。语法如下:

RETURN QUERY <SQL查询>;

你也可以组合多个查询:

RETURN QUERY <SQL查询1>;
RETURN QUERY <SQL查询2>;

例子1:带 RETURN QUERY 的函数

来写个函数,返回指定小组的学生列表。

CREATE OR REPLACE FUNCTION get_students_by_group(group_name TEXT)
RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
    RETURN QUERY
    SELECT id, name 
    FROM students
    WHERE group_name = group_name;
END;
$$ LANGUAGE plpgsql;

现在调用这个函数:

SELECT * FROM get_students_by_group('数学');

为了测试函数,先建个 students 表并插入点数据:

CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
group_name TEXT NOT NULL
);

INSERT INTO students (name, group_name) VALUES
('Otto Song',     '物理'),
('Alex Lin',      '数学'),
('Anna Vel',      '数学'),
('Maria Chi',     '历史');

结果:

id name
2 Alex Lin
3 Anna Vel

你看,这个函数用起来就像普通 SQL 查询一样。

例子2:合并多个查询

如果你想返回多个表合并的数据怎么办?比如我们想返回学生和他们选的课程列表。

CREATE OR REPLACE FUNCTION get_students_and_courses()
RETURNS TABLE(student_name TEXT, course_name TEXT) AS $$
BEGIN
    RETURN QUERY
    SELECT s.name, c.name
    FROM students s
    JOIN enrollments e ON s.id = e.student_id
    JOIN courses c ON e.course_id = c.id;
END;
$$ LANGUAGE plpgsql;

先建三个表:students、courses 和 enrollments,然后插入点数据:

-- 学生表
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);

-- 课程表
CREATE TABLE courses (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);

-- 选课表(关联表)
CREATE TABLE enrollments (
student_id INT REFERENCES students(id),
course_id INT REFERENCES courses(id)
);

-- 插入学生
INSERT INTO students (name) VALUES
('Otto Song'),
('Alex Lin'),
('Anna Vel'),
('Maria Chi');

-- 插入课程
INSERT INTO courses (name) VALUES
('数学'),
('物理'),
('历史');

-- 插入选课记录
INSERT INTO enrollments (student_id, course_id) VALUES
(1, 2), -- Otto -> 物理
(2, 1), -- Alex -> 数学
(3, 1), -- Anna -> 数学
(4, 3); -- Maria -> 历史

这时调用函数:

SELECT * FROM get_students_and_courses();

你会得到这样的结果:

student_name course_name
Otto Song 物理
Alex Lin 数学
Anna Vel 数学
Maria Chi 历史

这个函数把三个表的数据合并起来,清楚地展示了每个学生选了什么课。

把 RAISE NOTICE 和 RETURN QUERY 结合用

有时候你会想在一个函数里同时用 RETURN QUERY 和 RAISE NOTICE,这样既能返回数据,又能看到执行过程中的消息。

比如下面这个函数,一边返回学生数据,一边输出消息让你知道进度:

CREATE OR REPLACE FUNCTION debug_students()
RETURNS TABLE(student_id INT, student_name TEXT) AS $$
DECLARE
    count_students INT;
BEGIN
    -- 统计学生数量
    SELECT COUNT(*) INTO count_students FROM students;
    RAISE NOTICE '学生总数: %', count_students;

    -- 返回学生数据
    RETURN QUERY
    SELECT id, name FROM students;

    RAISE NOTICE '函数执行完毕。';
END;
$$ LANGUAGE plpgsql;

如果 students 表还没建,先建一个并插入数据:

CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);

INSERT INTO students (name) VALUES
('Otto Song'),
('Alex Lin'),
('Anna Vel'),
('Maria Chi');

现在调用函数:

SELECT * FROM debug_students();

你会同时看到数据和消息:

student_id student_name
1 Otto Song
2 Alex Lin
3 Anna Vel
4 Maria Chi

控制台输出消息:

NOTICE:  学生总数: 4
NOTICE:  函数执行完毕。

常见错误

RAISE NOTICE 变量错误: 如果你忘了声明变量,或者变量名写错了,会报 variable does not exist 错。记得检查变量都声明对了。

返回类型错误: 如果你用了 RETURN QUERY,但函数没写 RETURNS TABLE,PostgreSQL 会报错。一定要保证返回类型和你实际返回的数据一致。

RAISE 占位符错误: 如果 % 占位符数量和变量数量不一致,也会报错。比如:

RAISE NOTICE '值: %, %', value1;

这样会因为少了第二个变量而报错。

2
任务
SQL SELF, 第 50 级, 课程 3
已锁定
结合 RAISE NOTICE 和 RETURN QUERY
结合 RAISE NOTICE 和 RETURN QUERY
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION