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 'Загальна кількість студентів: %', 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-запити (SELECT, INSERT і т.д.).
  • Маніпулювати даними.
  • Використовувати керуючі конструкції (IF, LOOP і т.д.).
  • Виводити дебажні повідомлення через 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 'Student ID % записаний на % курсів.', student_id, course_count;
EXCEPTION
    WHEN OTHERS THEN
        RAISE NOTICE 'Виникла помилка під час обробки 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 'Помилка: %', SQLERRM;
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ