Іноді в циклі все йде по плану — аж поки не з’являється причина зупинитися раніше. На щастя, PL/pgSQL дає нам зручні інструменти, щоб керувати цим процесом.
Переривання циклу за допомогою EXIT
Іноді виконання циклу треба завершити раніше, ніж він сам дійде до кінця. Це може бути, наприклад, коли знайдено потрібне значення, виявлено помилку або завершено ітерації за якоюсь умовою. У таких ситуаціях ми використовуємо EXIT.
EXIT — це спосіб "сказати" циклу: "Досить, ти зробив свою роботу, час зупинитися".
Синтаксис EXIT дуже простий:
EXIT WHEN умова;
Тут ключова фраза WHEN вказує, за якої умови виконання циклу буде завершено. Якщо умову не вказано, EXIT просто миттєво завершує виконання поточного циклу.
Приклад: завершення циклу, коли знайдено задане значення
Припустимо, у нас є стовпець із номерами студентів, і ми хочемо знайти студента з конкретним ідентифікатором. Як тільки студент знайдений, цикл треба завершити.
DO $$
DECLARE
student_id INT;
BEGIN
FOR student_id IN 1..100 LOOP
RAISE NOTICE 'Перевіряю student ID: %', student_id;
-- Якщо знайшли потрібного студента, завершуємо цикл
IF student_id = 42 THEN
RAISE NOTICE 'Студент з ID 42 знайдений!';
EXIT;
END IF;
END LOOP;
END $$;
У цьому прикладі цикл перебирає числа від 1 до 100, перевіряючи кожного "студента". Як тільки ID 42 знайдено, цикл виводить повідомлення і завершує виконання.
Пропуск ітерації за допомогою CONTINUE
Бувають ситуації, коли всередині циклу треба пропустити певні ітерації, але при цьому продовжити виконання наступної ітерації. Це особливо корисно, якщо ти хочеш ігнорувати "непотрібні" дані або пропустити кроки для специфічних умов.
CONTINUE каже: "Окей, ця умова нам не підходить, просто переходимо до наступної ітерації".
CONTINUE працює за тим же принципом, що й EXIT, тільки замість завершення циклу він пропускає поточну ітерацію:
CONTINUE WHEN умова;
Якщо умова виконується, поточна ітерація завершиться, і виконання перейде до наступної.
Приклад: пропуск парних чисел
У цьому прикладі будемо перебирати числа від 1 до 10, але ігнорувати парні числа, виводячи тільки непарні.
DO $$
DECLARE
num INT;
BEGIN
FOR num IN 1..10 LOOP
-- Пропускаємо парні числа
IF num % 2 = 0 THEN
CONTINUE;
END IF;
RAISE NOTICE 'Непарне число: %', num;
END LOOP;
END $$;
Тут CONTINUE пропускає всі ітерації, де num % 2 = 0 (тобто число парне). Як результат, у лог будуть виведені тільки непарні числа.
Комбінування EXIT та CONTINUE
EXIT і CONTINUE можна використовувати разом, щоб керувати циклом більш гнучко. Наприклад, ти можеш пропускати непотрібні ітерації за допомогою CONTINUE, але завершувати весь цикл, якщо знайдено щось важливе.
Ось приклад, де ми пропускаємо всі числа, кратні 3, але завершуємо цикл, як тільки досягаємо числа 15.
DO $$
DECLARE
num INT;
BEGIN
FOR num IN 1..20 LOOP
-- Пропускаємо числа, кратні 3
IF num % 3 = 0 THEN
CONTINUE;
END IF;
-- Завершуємо цикл, якщо число дорівнює 15
IF num = 15 THEN
RAISE NOTICE 'Зупиняюсь на числі %', num;
EXIT;
END IF;
RAISE NOTICE 'Поточне число: %', num;
END LOOP;
END $$;
Тут цикл працює так:
- Числа, кратні 3, пропускаються (
CONTINUE). - Якщо число дорівнює 15, цикл завершує виконання (
EXIT). - Всі інші числа виводяться.
Просунутий приклад: пропуск некоректних даних і завершення при критичній помилці
Тепер давай уявимо більш реальну задачу. Ми хочемо обробити список студентів, перевіряючи їхні дані. Некоректні записи будемо пропускати, а у випадку "критичної помилки" припиняти обробку.
DO $$
DECLARE
student RECORD;
BEGIN
FOR student IN
SELECT * FROM students
LOOP
-- Пропускаємо записи з некоректними даними
IF student.name IS NULL THEN
RAISE NOTICE 'Пропускаю студента з ID %: Відсутнє ім’я', student.id;
CONTINUE;
END IF;
-- Завершуємо цикл при критичній помилці
IF student.status = 'ERROR' THEN
RAISE EXCEPTION 'Критична помилка для студента з ID %', student.id;
EXIT; -- Цей рядок фактично буде зайвим, бо RAISE EXCEPTION завершує виконання.
END IF;
-- Обробка запису
RAISE NOTICE 'Обробляю студента: %', student.name;
END LOOP;
END $$;
У цьому прикладі CONTINUE допомагає пропустити студентів із відсутнім ім’ям, а EXIT (разом із RAISE EXCEPTION) завершує цикл при виявленні серйозної помилки.
Практичні поради та типові помилки
Не забувай про логіку умов. Неправильне використання умовних виразів усередині EXIT WHEN або CONTINUE WHEN може призвести до неочікуваної поведінки. Наприклад, цикл може завершитися раніше часу або пропустити важливі дані.
Надмірне використання CONTINUE. Якщо твій код забитий перевірками з CONTINUE, можливо, варто переглянути логіку циклу, щоб зробити її простішою.
Не плутай EXIT і RETURN. EXIT завершує тільки поточний цикл, а RETURN завершує виконання функції повністю.
Будь обережний з нескінченними циклами. Якщо ти використовуєш цикл LOOP без чіткої умови завершення, забудеш про EXIT — і твій цикл може працювати вічно.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ