Цикли дозволяють виконувати блок коду кілька разів поспіль, поки виконується певна умова або поки йде ітерація по якомусь набору даних. Це дуже корисно для автоматизації задач, обробки великих обсягів даних чи виконання повторюваних дій.
Уяви, що тобі треба вручну роздати цукерки всім дітям у групі. Це буде хаос! Замість цього ти можеш пройтись по списку дітей і кожному по черзі дати цукерку. У цьому сценарії "прохід по списку" — це цикл.
У PostgreSQL підтримується кілька видів циклів:
LOOP— універсальний цикл, який виконується доти, поки явно не буде зупинений.FOR— цикл із заданою кількістю ітерацій по діапазону чисел або результату запиту.WHILE— цикл, який виконується доти, поки умова істинна.
Давай розберемо кожен вид окремо.
Нескінченний цикл:LOOP
LOOP — це базова форма циклу в PL/pgSQL, яка повторює виконання блоку коду. Цей цикл працює нескінченно, і його треба завершувати вручну через команду EXIT.
Синтаксис:
LOOP
-- Твій код тут
END LOOP;
Ось приклад. Порахуємо суму чисел від 1 до 10 за допомогою LOOP:
DO $$
DECLARE
counter INT := 1;
sum INT := 0;
BEGIN
LOOP
sum := sum + counter; -- додаємо поточне значення лічильника
counter := counter + 1; -- збільшуємо лічильник
-- Завершуємо цикл, якщо лічильник більше 10
IF counter > 10 THEN
EXIT;
END IF;
END LOOP;
RAISE NOTICE 'Сума чисел від 1 до 10: %', sum;
END $$;
- Змінна
counterзбільшується на кожній ітерації. - Умова
IF counter > 10 THEN EXIT;завершує цикл, коли лічильник перевищує 10. - В кінці виводиться сума чисел.
Цикл по діапазону або набору даних: FOR
Другий тип циклу, FOR, використовується для ітерації по:
- Діапазону чисел.
- Результату SQL-запиту.
Цикл по діапазону чисел
Синтаксис:
FOR variable IN [REVERSE] start..end LOOP
-- Твій код тут
END LOOP;
Виведемо числа від 1 до 5:
DO $$
BEGIN
FOR i IN 1..5 LOOP
RAISE NOTICE 'Поточне значення: %', i;
END LOOP;
END $$;
Приклад із зворотнім порядком:
DO $$
BEGIN
FOR i IN REVERSE 5..1 LOOP
RAISE NOTICE 'Зворотній порядок: %', i;
END LOOP;
END $$;
Цикл по результату SQL-запиту
Цей варіант корисний для обробки рядків таблиці.
Синтаксис:
FOR variable IN QUERY (SELECT ...) LOOP
-- Твій код тут
END LOOP;
Ось приклад ітерації по рядках таблиці students:
DO $$
DECLARE
student_name TEXT;
BEGIN
FOR student_name IN QUERY (SELECT name FROM students) LOOP
RAISE NOTICE 'Привіт, %!', student_name;
END LOOP;
END $$;
Умовний цикл:WHILE
WHILE виконується доти, поки задана умова істинна.
Синтаксис:
WHILE умова LOOP
-- Твій код тут
END LOOP;
Давай порахуємо суму чисел від 1 до 10 за допомогою WHILE:
DO $$
DECLARE
counter INT := 1;
sum INT := 0;
BEGIN
WHILE counter <= 10 LOOP
sum := sum + counter;
counter := counter + 1;
END LOOP;
RAISE NOTICE 'Сума чисел від 1 до 10: %', sum;
END $$;
Приклади з реального життя
Тепер, коли ми розібралися з основами циклів, давай глянемо на приклади їх використання.
Приклад 1: генерація таблиці множення
DO $$
DECLARE
i INT;
j INT;
BEGIN
FOR i IN 1..5 LOOP
FOR j IN 1..5 LOOP
RAISE NOTICE '% x % = %', i, j, i * j;
END LOOP;
END LOOP;
END $$;
Приклад 2: ітерація по результатах запиту. Припустимо, у нас є таблиця products з полями id і price. Оновимо всі ціни, збільшивши їх на 10%.
DO $$
DECLARE
prod RECORD;
BEGIN
FOR prod IN QUERY (SELECT id, price FROM products) LOOP
UPDATE products
SET price = prod.price * 1.1
WHERE id = prod.id;
END LOOP;
END $$;
Типові помилки і як їх уникнути
Зациклення в LOOP або WHILE. Якщо забути додати умову виходу (EXIT або коректну умову в WHILE), цикл ніколи не завершиться. Це приблизно як їздити на машині без гальм.
Помилка при ітерації по результату запиту. Якщо структура результату не співпадає з очікуваною, можна зловити помилку в циклі FOR IN QUERY.
Неоптимальні запити всередині циклів. Наприклад, виконання UPDATE у кожній ітерації може дуже сповільнити виконання. У таких випадках краще використати один SQL-запит замість циклу.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ