JavaRush /Курсы /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 'Total number of students: %', student_count;
EXCEPTION
    -- Здесь обрабатываются ошибки
    WHEN OTHERS THEN
        RAISE NOTICE 'An error occurred.';
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-запросы (SELECT, INSERT, и т.д.).
  • Манипулировать данными.
  • Использовать управляющие конструкции (IF, LOOP, и т.д.).
  • Выводить отладочные сообщения с помощью RAISE.

Пример:

BEGIN
    SELECT COUNT(*) INTO student_count FROM students;
    IF student_count > 0 THEN
        RAISE NOTICE 'We have students!';
    ELSE
        RAISE NOTICE 'No students found.';
    END IF;
END;
  1. EXCEPTION — обработка ошибок (опционально).

Если в процессе выполнения блока произойдет ошибка, секция EXCEPTION позволяет нам перехватить её и сделать что-то полезное — например, вывести сообщение или выполнить альтернативный код.

Пример:

BEGIN
    SELECT COUNT(*) INTO student_count FROM non_existing_table; -- Ошибка!
EXCEPTION
    WHEN OTHERS THEN
        RAISE NOTICE 'Oops, something went wrong!';
END;

Реальный пример: подсчёт студентов

Теперь соберём все части вместе в пример, который может пригодиться в реальной жизни. Напишем блок PL/pgSQL, который считает количество студентов в таблице students и выводит сообщение.

DO $$
DECLARE
    total_students INT; -- Переменная для хранения количества студентов
BEGIN
    -- Подсчитываем количество студентов
    SELECT COUNT(*) INTO total_students FROM students;

    -- Выводим сообщение с результатом
    RAISE NOTICE 'Number of students: %', total_students;
EXCEPTION
    -- Обрабатываем возможные ошибки, например, если таблица не существует
    WHEN OTHERS THEN
        RAISE NOTICE 'An error occurred while counting students.';
END;
$$;

Вызов этого блока выведет сообщение в консоль. Например: Number of students: 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: %, Age: %', 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 'Student ID % is enrolled in % courses.', student_id, course_count;
EXCEPTION
    WHEN OTHERS THEN
        RAISE NOTICE 'An error occurred while processing student 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 'Error: %', SQLERRM;
2
Задача
SQL SELF, 49 уровень, 3 лекция
Недоступна
Подсчёт записей в таблице
Подсчёт записей в таблице
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ