Практика: Триггеры и правила
Онлайн редактор кода для PostgreSQL
Здесь вы можете попробовать свои силы в программировании на языке SQL для работы с PostgreSQL. Для этого мы предоставляем вам онлайн редактор кода, в котором вы можете написать свой код и запустить его.
❗️ При обновлении страницы код пропадёт, по этому, сохраните свой код куда-нибудь, если он важный.
Задание 1 — BEFORE триггеры: валидация и нормализация
Задание 1: BEFORE-триггеры для защиты и нормализации данных
⏱️ Примерное время: 15-30 минутСоздай триггеры, которые изменяют/блокируют данные перед записью.
Требования:
- создай триггерную функцию + триггер BEFORE INSERT OR UPDATE
- используй NEW и OLD
- верни NEW (или NULL для отмены операции)
- протестируй INSERT и UPDATE, покажи, что триггер сработал
Пример:
CREATE OR REPLACE FUNCTION set_updated_at()
RETURNS TRIGGER LANGUAGE plpgsql AS $$
BEGIN
NEW.updated_at := NOW();
RETURN NEW;
END;
$$;
CREATE TRIGGER trg_products_updated_at
BEFORE UPDATE ON products
FOR EACH ROW
EXECUTE FUNCTION set_updated_at();
Задание 2 — AFTER триггеры: аудит, пересчёт, уведомления
Задание 2: AFTER-триггеры для реакции на изменения
⏱️ Примерное время: 25-45 минутСоздай триггеры, которые реагируют после изменения данных.
Требования:
- триггер AFTER INSERT OR UPDATE OR DELETE (или нужные события)
- используй TG_OP, TG_LEVEL, NEW/OLD
- протестируй массовую операцию (INSERT 10 строк, UPDATE 50 строк)
- покажи, как триггер влияет на производительность (EXPLAIN ANALYZE)
Пример:
CREATE OR REPLACE FUNCTION recalc_order_total()
RETURNS TRIGGER LANGUAGE plpgsql AS $$
DECLARE
v_order_id INT := COALESCE(NEW.order_id, OLD.order_id);
BEGIN
UPDATE orders
SET total = (SELECT SUM(quantity * unit_price) FROM order_items WHERE order_id = v_order_id)
WHERE order_id = v_order_id;
RETURN COALESCE(NEW, OLD);
END;
$$;
CREATE TRIGGER trg_order_items_recalc
AFTER INSERT OR UPDATE OR DELETE ON order_items
FOR EACH ROW
EXECUTE FUNCTION recalc_order_total();
Задание 3 — INSTEAD OF + Rules
Задание 3: INSTEAD OF триггеры и Rules
⏱️ Примерное время: 30-50 минутСделай обновляемые представления и правила.
Требования:
- создай view + INSTEAD OF триггер (или Rule)
- реализуй INSERT/UPDATE/DELETE через представление
- протестируй, что обычный UPDATE/DELETE на view не работает без триггера
- сравни поведение Rules и триггеров (если возможно)
Пример:
CREATE VIEW products_live AS SELECT * FROM products WHERE is_active;
CREATE OR REPLACE FUNCTION soft_delete_products()
RETURNS TRIGGER LANGUAGE plpgsql AS $$
BEGIN
UPDATE products SET is_active = false, deleted_at = NOW()
WHERE product_id = OLD.product_id;
RETURN NULL;
END;
$$;
CREATE TRIGGER trg_products_live_delete
INSTEAD OF DELETE ON products_live
FOR EACH ROW EXECUTE FUNCTION soft_delete_products();
Задание 4 — Универсальный аудит-триггер + WHEN
Задание 4: Универсальный аудит + условные триггеры
⏱️ Примерное время: 45-75 минутСоздай один триггер для всей схемы + условные срабатывания.
Требования:
- одна универсальная функция (с TG_ARGV для PK-колонки)
- триггер на несколько таблиц с разными PK
- используй WHEN для фильтрации (например, WHEN NEW.price <> OLD.price)
- добавь поле changed_fields (массив изменённых колонок)
- протестируй на INSERT/UPDATE/DELETE + массовые операции
Пример:
CREATE OR REPLACE FUNCTION generic_audit()
RETURNS TRIGGER LANGUAGE plpgsql AS $$
DECLARE
v_pk TEXT := TG_ARGV[0];
v_id TEXT;
v_changed TEXT[] := '{}';
BEGIN
-- Определяем ID
EXECUTE format('SELECT ($1).%I::TEXT', v_pk) INTO v_id USING NEW;
-- Логика аудита...
RETURN NEW;
END;
$$;
CREATE TRIGGER trg_products_audit
AFTER INSERT OR UPDATE OR DELETE ON products
FOR EACH ROW EXECUTE FUNCTION generic_audit('product_id');
Задание 5 — Итоговый проект: полная система аудита + soft-delete + пересчёты
Задание 5: Полноценная система триггеров (итоговое)
⏱️ Примерное время: 90-180 минутСоздай самодостаточную систему с триггерами.
Требования:
- минимум 5–7 триггеров (BEFORE + AFTER + INSTEAD OF)
- универсальный аудит-триггер + минимум 2 специализированных
- soft-delete хотя бы на одной таблице
- пересчёт итогов (total, rating, balance и т.д.)
- контроль целостности (остатки, баланс, лимиты)
- условные триггеры (WHEN) + логирование
- тестовые сценарии: массовые INSERT/UPDATE/DELETE + проверка аудита
- документация: COMMENT ON TRIGGER + описание логики
Это задание — полноценный кейс для портфолио или собеседования на позицию DBA / Senior Backend.
подсказка
Триггеры — это контракт БД с самой собой.
Главные правила успеха:
- BEFORE → валидация и нормализация
- AFTER → аудит, пересчёт, уведомления
- INSTEAD OF → обновляемые представления
- WHEN → экономия производительности
- Универсальные функции + TG_ARGV → меньше кода
- Мониторинг: pg_stat_user_functions + EXPLAIN ANALYZE