CodeGym /课程 /SQL SELF /PL/pgSQL语法基础

PL/pgSQL语法基础

SQL SELF
第 49 级 , 课程 3
可用

咱们来深入了解一下PL/pgSQL,开始更灵活地用它写点东西吧。

代码块

PL/pgSQL里的代码块就是这个语言的核心构件。可以说,它就是我们函数、过程和各种“魔法”的骨架。代码块负责执行逻辑、处理数据、管理错误,全都装在一个“容器”里。

PL/pgSQL的代码块结构化,主要分三部分:

  1. DECLARE:声明变量(可选)。
  2. BEGIN ... END:主执行块,逻辑都在这里跑。
  3. EXCEPTION:错误处理(可选)。

打个比方:想象你在看菜谱。虽然菜谱开头会列材料,真正的“魔法”都发生在烹饪过程中。用PL/pgSQL的术语来说:

  • DECLARE —— 就是材料清单(变量)。
  • BEGIN ... END —— 这里就是炒菜、煮饭、搅拌的地方。
  • EXCEPTION —— 如果糊锅了怎么办的应急方案。

PL/pgSQL代码块语法

先看看代码块的整体结构,就像“骨架”一样。后面我们再加点肉(或者你喜欢的话,加点素奶酪)——也就是具体逻辑。

DO $$
DECLARE
    -- 这里声明变量
    student_count INT;
BEGIN
    -- 这里写逻辑
    SELECT COUNT(*) INTO student_count FROM students;
    RAISE NOTICE '学生总数: %', student_count;
EXCEPTION
    -- 这里处理错误
    WHEN OTHERS THEN
        RAISE NOTICE '发生了一个错误。';
END;
$$;

咱们一步步拆解下这个例子。

  1. DECLARE —— 这里声明变量。PL/pgSQL支持PostgreSQL几乎所有数据类型,从普通的INTEGER到很酷的JSONB都行。声明变量时,写上名字、类型,想要的话还能给个初始值。

例子:

DECLARE
    student_name TEXT;    -- 学生名字变量
    course_count INT := 0; -- 初始值设为0
    is_graduated BOOLEAN; -- 布尔变量

注意,变量可以初始化(像course_count),也可以不初始化。

  1. BEGIN ... END —— 主执行块。

这部分负责执行主要逻辑。你可以:

  • 执行SQL语句(SELECTINSERT等)。
  • 操作数据。
  • 用控制结构(IFLOOP等)。
  • RAISE输出调试信息。

例子:

BEGIN
    SELECT COUNT(*) INTO student_count FROM students;
    IF student_count > 0 THEN
        RAISE NOTICE '有学生!';
    ELSE
        RAISE NOTICE '没找到学生。';
    END IF;
END;
  1. EXCEPTION —— 错误处理(可选)。

如果执行过程中出错,EXCEPTION部分能让你捕获错误,做点有用的事——比如输出消息或者执行别的代码。

例子:

BEGIN
    SELECT COUNT(*) INTO student_count FROM non_existing_table; -- 错误!
EXCEPTION
    WHEN OTHERS THEN
        RAISE NOTICE '哎呀,出错了!';
END;

实际例子:统计学生数量

现在把所有部分拼一起,来个实际点的例子。写个PL/pgSQL块,统计students表里的学生数并输出消息。

DO $$
DECLARE
    total_students INT; -- 存学生数量的变量
BEGIN
    -- 统计学生数量
    SELECT COUNT(*) INTO total_students FROM students;

    -- 输出结果消息
    RAISE NOTICE '学生数量: %', total_students;
EXCEPTION
    -- 处理可能的错误,比如表不存在
    WHEN OTHERS THEN
        RAISE NOTICE '统计学生时发生了错误。';
END;
$$;

执行这个块会在控制台输出消息。例如:学生数量: 42

变量使用小技巧

来聊聊几个重要点:

给变量赋值。 要把数据存进变量,可以用SELECT INTO

SELECT COUNT(*) INTO total_students FROM students;

变量初始化。 如果声明变量时没赋值,默认就是NULL

比如:

DECLARE
    my_var INT; -- 值为NULL

RECORD类型变量。 这是个万能变量类型,可以存表里的一行。例子:

DECLARE
    student RECORD;
BEGIN
    SELECT * INTO student FROM students WHERE id = 1;
    RAISE NOTICE '学生名: %, 年龄: %', student.name, student.age;
END;

例子:统计学生的课程数

来做个实际任务:统计某个学生选了多少门课,并输出结果。

DO $$
DECLARE
    student_id INT := 1;   -- 学生ID
    course_count INT;      -- 课程数量变量
BEGIN
    -- 统计课程数量
    SELECT COUNT(*) INTO course_count
    FROM enrollments
    WHERE student_id = student_id;

    -- 输出消息
    RAISE NOTICE '学生ID % 选了 % 门课。', student_id, course_count;
EXCEPTION
    WHEN OTHERS THEN
        RAISE NOTICE '处理学生ID % 时发生了错误', student_id;
END;
$$;

这个块很灵活:你可以改student_id,查不同学生的课程数。

错误和如何避免

如果你觉得PL/pgSQL让你脑袋像微波炉里的小热狗一样炸,那很正常。刚开始经常会遇到“常见”错误。举几个例子:

没声明变量。 如果你忘了用DECLARE声明变量,PL/pgSQL会报错,说变量“不存在”。

NULL做判断。 变量声明了但没赋值,默认是NULL。这可能导致奇怪的行为。比如:

IF my_var = NULL THEN -- 不会生效!

应该用IS NULL

IF my_var IS NULL THEN

错误用法的EXCEPTION块。 有时候程序员捕获了所有错误(WHEN OTHERS),但啥也不做。这会把真正的问题藏起来。最好输出错误消息:

RAISE NOTICE '错误: %', SQLERRM;
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION