CREATE TRIGGER
CREATE TRIGGER — создать триггер
Синтаксис
CREATE [ CONSTRAINT ] TRIGGERимя
{ BEFORE | AFTER | INSTEAD OF } {событие
[ OR ... ] } ONимя_таблицы
[ FROMссылающаяся_таблица
] [ NOT DEFERRABLE | [ DEFERRABLE ] [ INITIALLY IMMEDIATE | INITIALLY DEFERRED ] ] [ FOR [ EACH ] { ROW | STATEMENT } ] [ WHEN (условие
) ] EXECUTE PROCEDUREимя_функции
(аргументы
) Здесь допускаетсясобытие
: INSERT UPDATE [ OFимя_столбца
[, ... ] ] DELETE TRUNCATE
Описание
CREATE TRIGGER
создаёт новый триггер. Триггер будет связан с указанной таблицей, представлением или сторонней таблицей и будет выполнять заданную функцию имя_функции
при определённых событиях.
Триггер можно настроить так, чтобы он срабатывал до операции со строкой (до проверки ограничений и попытки выполнить INSERT
, UPDATE
или DELETE
) или после её завершения (после проверки ограничений и выполнения INSERT
, UPDATE
или DELETE
), либо вместо операции (при добавлении, изменении и удалении строк в представлении). Если триггер срабатывает до или вместо события, он может пропустить операцию с текущей строкой, либо изменить добавляемую строку (только для операций INSERT
и UPDATE
). Если триггер срабатывает после события, он «видит» все изменения, включая результат действия других триггеров.
Триггер с пометкой FOR EACH ROW
вызывается один раз для каждой строки, изменяемой в процессе операции. Например, операция DELETE
, удаляющая 10 строк, приведёт к срабатыванию всех триггеров ON DELETE
в целевом отношении 10 раз подряд, по одному разу для каждой удаляемой строки. Триггер с пометкой FOR EACH STATEMENT
, напротив, вызывается только один раз для конкретной операции, вне зависимости от того, как много строк она изменила (в частности, при выполнении операции, изменяющей ноль строк, всё равно будут вызваны все триггеры FOR EACH STATEMENT
). Заметьте, что при выполнении INSERT
с предложением ON CONFLICT DO UPDATE
сработают оба триггера уровня операторов, для INSERT
и для UPDATE
.
Триггеры, срабатывающие в режиме INSTEAD OF
, должны быть помечены FOR EACH ROW
и могут быть определены только для представлений. Триггеры BEFORE
и AFTER
для представлений должны быть помечены FOR EACH STATEMENT
.
Кроме того, триггеры можно определить и для команды TRUNCATE
, но только типа FOR EACH STATEMENT
.
В следующей таблице перечисляются типы триггеров, которые могут использоваться для таблиц, представлений и сторонних таблиц:
Когда | Событие | На уровне строк | На уровне оператора |
---|---|---|---|
BEFORE | INSERT /UPDATE /DELETE | Таблицы и сторонние таблицы | Таблицы, представления и сторонние таблицы |
TRUNCATE | — | Таблицы | |
AFTER | INSERT /UPDATE /DELETE | Таблицы и сторонние таблицы | Таблицы, представления и сторонние таблицы |
TRUNCATE | — | Таблицы | |
INSTEAD OF | INSERT /UPDATE /DELETE | Представления | — |
TRUNCATE | — | — |
Кроме того, в определении триггера можно указать логическое условие WHEN
, которое определит, вызывать триггер или нет. В триггерах на уровне строк условия WHEN
могут проверять старые и/или новые значения столбцов в строке. Триггеры на уровне оператора так же могут содержать условие WHEN
, хотя для них это не столь полезно, так как в этом условии нельзя ссылаться на какие-либо значения в таблице.
Если для одного события определено несколько триггеров одного типа, они будут срабатывать в алфавитном порядке их имён.
Когда указывается параметр CONSTRAINT
, эта команда создаёт триггер ограничения. Он подобен обычным триггерам, но отличается тем, что время его срабатывания можно изменить командой SET CONSTRAINTS. Триггеры ограничений должны работать в режиме AFTER ROW
. Они могут срабатывать либо в конце оператора, вызвавшего целевое событие, либо в конце содержащей его транзакции; в последнем случае они называются отложенными. Срабатывание ожидающего отложенного триггера можно вызвать немедленно, воспользовавшись командой SET CONSTRAINTS
. Предполагается, что триггеры ограничений будут генерировать исключения при нарушении ограничений.
SELECT
не изменяет никакие строки, поэтому создавать триггеры для SELECT
нельзя. В случае подобной потребности будут более уместны правила и представления.
За дополнительными сведениями о триггерах обратитесь к Главе 37.
Параметры
имя
Имя, назначаемое новому триггеру. Это имя должно отличаться от имени любого другого триггера в этой же таблице. Имя не может быть дополнено схемой — триггер наследует схему от своей таблицы. Для триггеров ограничений это имя также используется, когда требуется скорректировать поведение триггера с помощью команды
SET CONSTRAINTS
.BEFORE
AFTER
INSTEAD OF
Определяет, будет ли заданная функция вызываться до, после или вместо события. Для триггера ограничения можно указать только
AFTER
.событие
Принимает одно из значений:
INSERT
,UPDATE
,DELETE
илиTRUNCATE
; этот параметр определяет событие, при котором будет срабатывать триггер. Несколько событий можно указать, добавив между ними словоOR
.Для событий
UPDATE
можно указать список столбцов, используя такую запись:UPDATE OF
имя_столбца1
[,имя_столбца2
... ]Такой триггер сработает, только если в указанном в целевой команде
UPDATE
списке столбцов окажется минимум один из перечисленных.Для событий
INSTEAD OF UPDATE
список столбцов задать нельзя.имя_таблицы
Имя (возможно, дополненное схемой) таблицы, представления или сторонней таблицы, для которых предназначен триггер.
ссылающаяся_таблица
Имя (возможно, дополненное схемой) другой таблицы, на которую ссылается ограничение. Оно используется для ограничений внешнего ключа и не рекомендуется для обычного применения. Это указание допускается только для триггеров ограничений.
DEFERRABLE
NOT DEFERRABLE
INITIALLY IMMEDIATE
INITIALLY DEFERRED
Время срабатывания триггера по умолчанию. Подробнее возможные варианты описаны в документации CREATE TABLE. Это указание допускается только для триггеров ограничений.
FOR EACH ROW
FOR EACH STATEMENT
Определяет, будет ли процедура триггера срабатывать один раз для каждой строки, либо для SQL-оператора. Если не указано ничего, подразумевается
FOR EACH STATEMENT
(для оператора). Для триггеров ограничений можно указать толькоFOR EACH ROW
.условие
Логическое выражение, определяющее, будет ли выполняться функция триггера. Если для триггера задано указание
WHEN
, функция будет вызываться, только когдаусловие
возвращаетtrue
. В триггерахFOR EACH ROW
условиеWHEN
может ссылаться на значения столбца в старой и/или новой строке, в видеOLD.
иимя_столбца
NEW.
, соответственно. Разумеется, триггерыимя_столбца
INSERT
не могут ссылаться наOLD
, а триггерыDELETE
не могут ссылаться наNEW
.Триггеры
INSTEAD OF
не поддерживают условияWHEN
.В настоящее время выражения
WHEN
не могут содержать подзапросы.Учтите, что для триггеров ограничений вычисление условия
WHEN
не откладывается, а выполняется немедленно после операции, изменяющей строки. Если результат условия — ложь, сам триггер не откладывается для последующего выполнения.имя_функции
Заданная пользователем функция, объявленная как функция без аргументов и возвращающая тип
trigger
, которая будет вызываться при срабатывании триггера.аргументы
Необязательный список аргументов через запятую, которые будут переданы функции при срабатывании триггера. В качестве аргументов функции передаются строковые константы. И хотя в этом списке можно записать и простые имена или числовые константы, они тоже будут преобразованы в строки. Порядок обращения к таким аргументам в функции триггера может отличаться от обычных аргументов, поэтому его следует уточнить в описании языка реализации этой функции.
Замечания
Чтобы создать триггер, пользователь должен иметь право TRIGGER
для этой таблицы. Также пользователь должен иметь право EXECUTE
для триггерной функции.
Для удаления триггера применяется команда DROP TRIGGER.
Триггер для избранных столбцов (определённый с помощью UPDATE OF
) будет срабатывать, когда его столбцы перечислены в качестве целевых в списке имя_столбца
SET
команды UPDATE
. Изменения, вносимые в строки триггерами BEFORE UPDATE
, при этом не учитываются, поэтому значения столбцов можно изменить так, что триггер не сработает. И наоборот, при выполнении команды UPDATE ... SET x = x ...
триггер для столбца x
сработает, хотя значение столбца не меняется.
Некоторые общие задачи можно решить с применением встроенных триггерных функций, обойдясь без написания собственного кода; см. Раздел 9.27.
В триггере BEFORE
условие WHEN
вычисляется непосредственно перед возможным вызовом функции, поэтому проверка WHEN
существенно не отличается от проверки того же условия в начале функции триггера. В частности, учтите, что строка NEW
, которую видит ограничение, содержит текущие значения, возможно изменённые предыдущими триггерами. Кроме того, в триггере BEFORE
условие WHEN
не может проверять системные столбцы в строке NEW
(например, oid
), так как они ещё не установлены.
В триггере AFTER
условие WHEN
проверяется сразу после изменения строки, и если оно выполняется, событие запоминается, чтобы вызвать триггер в конце оператора. Если же для триггера AFTER
условие WHEN
не выполняется, нет необходимости запоминать событие для последующей обработки или заново перечитывать строку в конце оператора. Это приводит к значительному ускорению операторов, изменяющих множество строк, когда триггер должен срабатывать только для некоторых из них.
Триггеры уровня операторов для представления срабатывают, только если операция с представлением обрабатывается триггером уровня строк INSTEAD OF
. Если операция обрабатывается правилом INSTEAD
, то вместо исходного оператора, обращающегося к представлению, выполняются те операторы, что генерирует правило, поэтому вызываться будут триггеры, связанные с таблицами, к которым обращаются эти заменяющие операторы. Аналогично, для автоматически изменяемого представления выполнение операции сводится к переписыванию оператора в виде операции с базовой таблицей представления, так что срабатывать будут триггеры уровня операторов для базовой таблицы.
В PostgreSQL до версии 7.3 обязательно требовалось объявлять триггерные функции, как возвращающие фиктивный тип opaque
, а не trigger
. Для поддержки загрузки старых файлов экспорта БД, команда CREATE TRIGGER
принимает функции с объявленным типом результата opaque
, но при этом выдаётся предупреждение и тип результата меняется на trigger
.
Примеры
Выполнение функции check_account_update
перед любым изменением строк в таблице accounts
:
CREATE TRIGGER check_update BEFORE UPDATE ON accounts FOR EACH ROW EXECUTE PROCEDURE check_account_update();
То же самое, но функция триггера будет выполняться, только если столбец balance
присутствует в списке целевых столбцов команды UPDATE
:
CREATE TRIGGER check_update BEFORE UPDATE OF balance ON accounts FOR EACH ROW EXECUTE PROCEDURE check_account_update();
В этом примере функция будет выполняться, если значение столбца balance
в действительности изменилось:
CREATE TRIGGER check_update BEFORE UPDATE ON accounts FOR EACH ROW WHEN (OLD.balance IS DISTINCT FROM NEW.balance) EXECUTE PROCEDURE check_account_update();
Вызов функции, ведущей журнал изменений в accounts
, но только если что-то изменилось:
CREATE TRIGGER log_update AFTER UPDATE ON accounts FOR EACH ROW WHEN (OLD.* IS DISTINCT FROM NEW.*) EXECUTE PROCEDURE log_account_update();
Выполнение для каждой строки функции view_insert_row
, которая будет вставлять строки в нижележащие таблицы представления:
CREATE TRIGGER view_insert INSTEAD OF INSERT ON my_view FOR EACH ROW EXECUTE PROCEDURE view_insert_row();
В Разделе 37.4 приведён полный пример функции триггера, написанной на C.
Совместимость
Оператор CREATE TRIGGER
в PostgreSQL реализует подмножество возможностей, описанных в стандарте SQL. В настоящее время в нём отсутствует следующая функциональность:
SQL позволяет определить синонимы для строк «old» и «new» или таблиц, которые затем можно будет использовать в определении действия триггера (например,
CREATE TRIGGER ... ON имя_таблицы REFERENCING OLD ROW AS некоторое_имя NEW ROW AS другое_имя...
). PostgreSQL позволяет писать процедуры триггеров на различных языках, так что механизм доступа к данным зависит от конкретного языка.PostgreSQL не позволяет обращаться к старой и новой таблице в триггерах на уровне оператора, т. е. к таблицам, содержащим все старые и/или новые строки, обозначаемые как
OLD TABLE
иNEW TABLE
в стандарте SQL.PostgreSQL позволяет задать в качестве действия триггера только функцию, определённую пользователем. Стандарт допускает также выполнение ряда других команд SQL, например,
CREATE TABLE
. Однако это ограничение несложно преодолеть, создав пользовательскую функцию, выполняющую требуемые команды.
В стандарте SQL определено, что несколько триггеров должны срабатывать по порядку создания. PostgreSQL упорядочивает их по именам, так как это было признано более удобным.
В стандарте SQL определено, что триггеры BEFORE DELETE
при каскадном удалении срабатывают после завершения каскадного DELETE
. В PostgreSQL триггеры BEFORE DELETE
всегда срабатывают перед операцией удаления, даже если она каскадная. Это поведение выбрано как более логичное. Ещё одно отклонение от стандарта проявляется, когда триггеры BEFORE
, срабатывающие в результате ссылочной операции, изменяют строки или не дают выполнить изменение. Это может привести к нарушению ограничений или сохранению данных, не соблюдающих ссылочную целостность.
Возможность задать несколько действий для одного триггера с помощью ключевого слова OR
— реализованное в PostgreSQL расширение стандарта SQL.
Возможность вызывать триггеры для TRUNCATE
— реализованное в PostgreSQL расширение стандарта SQL, как и возможность определять триггеры на уровне оператора для представлений.
CREATE CONSTRAINT TRIGGER
— реализованное в PostgreSQL расширение стандарта SQL.