0Pricing
SQL Academy · Урок

Обновляемые представления и триггеры INSTEAD OF

Делайте представления непосредственно обновляемыми или используйте триггеры INSTEAD OF, когда представление агрегирует или объединяет данные

«Обновляемые представления и триггеры INSTEAD OF» — бесплатный урок SQL Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения SQL Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс SQL Academy содержит 4 уроков всего.

Автоматически изменяемые представления

PostgreSQL автоматически делает простые представления изменяемыми. Операции INSERT/UPDATE/DELETE над представлением переписываются в такие же операции над базовой таблицей:

CREATE VIEW active_users AS
  SELECT id, email, full_name FROM users WHERE deleted_at IS NULL;

UPDATE active_users SET full_name = 'Alice' WHERE id = 1;
-- Translates to UPDATE on the users table.

Требования для автоматического обновления

Представление должно:

  • Ссылаться ровно на одну базовую таблицу — ONE
  • Не содержать агрегатов, GROUP BY, HAVING, DISTINCT
  • Не содержать LIMIT, OFFSET
  • Не содержать операций над множествами (UNION и т. д.)
  • Напрямую отображать столбцы (без выражений в списке SELECT — или только с некоторыми исключениями)

WITH CHECK OPTION

Запрещает записи, из-за которых строки стали бы невидимыми в представлении:

CREATE VIEW active_users AS
  SELECT * FROM users WHERE deleted_at IS NULL
  WITH CHECK OPTION;

INSERT INTO active_users (email, deleted_at) VALUES (..., NOW());
-- ERROR — would create a row outside the view's WHERE.

Для сложных представлений нужен INSTEAD OF

Представления с объединениями, агрегатами или выражениями не обновляются автоматически. Необходимо написать триггер INSTEAD OF, который определяет смысл операции записи:

CREATE VIEW user_with_address AS
  SELECT u.id, u.email, a.city, a.country
  FROM users u JOIN addresses a ON a.user_id = u.id;

CREATE TRIGGER user_addr_update
INSTEAD OF UPDATE ON user_with_address
FOR EACH ROW EXECUTE FUNCTION update_user_addr();

Функция триггера INSTEAD OF

Функция определяет, в какие базовые таблицы выполнять запись:

CREATE FUNCTION update_user_addr() RETURNS TRIGGER AS $$
BEGIN
  UPDATE users SET email = NEW.email WHERE id = NEW.id;
  UPDATE addresses SET city = NEW.city, country = NEW.country WHERE user_id = NEW.id;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Когда INSTEAD OF лучше логики приложения

Если представление обновляют многие потребители, централизация логики обновления в триггере обеспечивает согласованность. Если обновления выполняет только одно приложение, оставьте логику в коде приложения.

SECURITY BARRIER

Не позволяйте планировщику проталкивать условия фильтрации в ненадёжных потребителей представления, чтобы предотвратить утечку информации через стоимость выполнения:

CREATE VIEW my_things AS
SELECT * FROM things WHERE owner_id = current_user_id()
WITH (security_barrier);

Безопасность на уровне строк как альтернатива

Современный PostgreSQL также поддерживает безопасность на уровне строк (RLS) в базовых таблицах — часто это чище, чем создание защищённых представлений.

ALTER TABLE things ENABLE ROW LEVEL SECURITY;
CREATE POLICY owner_only ON things USING (owner_id = current_user_id());

Рекурсивные представления

PostgreSQL поддерживает рекурсивные представления (иерархию, из которой можно выполнять SELECT):

CREATE RECURSIVE VIEW tree (id, parent_id, depth) AS
  SELECT id, parent_id, 0 FROM nodes WHERE parent_id IS NULL
  UNION ALL
  SELECT n.id, n.parent_id, t.depth + 1
  FROM nodes n JOIN tree t ON n.parent_id = t.id;

Разрешения

Выдавайте разрешение на представление, а не на базовые таблицы:

GRANT SELECT, UPDATE ON active_users TO app_user;

Замечание о производительности

Триггер INSTEAD OF срабатывает для каждой строки. Для массовых операций DML это медленно. Часто лучше, чтобы вызывающие стороны записывали данные непосредственно в базовые таблицы.

Итоги

Представления могут быть доступными для записи.

  • Простые представления: обновляются автоматически
  • Сложные представления: триггеры INSTEAD OF
  • WITH CHECK OPTION обеспечивает видимость строк
  • RLS часто предоставляет более чистую модель безопасности

Быстрая проверка

Вы определили представление, объединяющее две таблицы. Можно ли по умолчанию выполнить UPDATE через него?

Часто задаваемые вопросы

Урок «Обновляемые представления и триггеры INSTEAD OF» бесплатный?

Да — полный текст урока «Обновляемые представления и триггеры INSTEAD OF» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс SQL Academy, подпишись на CoddyKit PRO. Курс SQL Academy содержит 4 уроков всего.

Чему я научусь в уроке «Обновляемые представления и триггеры INSTEAD OF»?

Делайте представления непосредственно обновляемыми или используйте триггеры INSTEAD OF, когда представление агрегирует или объединяет данные Ты практикуешь SQL Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать SQL Academy?

Предыдущий опыт не требуется. SQL Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Обновляемые представления и триггеры INSTEAD OF»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке SQL Academy?

Да. Каждый урок SQL Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Обычные представления: логическое повторное использование
  2. Обновляемые представления и триггеры INSTEAD OF
  3. Материализованные представления и стратегии REFRESH
  4. Когда нужна предварительная агрегация
← Назад к SQL Academy