×
Мы обрабатываем cookies, чтобы сделать наш сайт удобнее и персонализированнее для вас. Подробнее: политика использования «cookies» и «политики конфиденциальности».

Для самостоятельной настройки ознакомьтесь с инструкцией

Дополнительные настройки cookies в браузерах

Файлы cookie автоматически загружаются в ваш браузер при посещении веб-сайта. У вас есть возможность управлять этими файлами. Если Вы не согласны с использованием файлов cookies, запретите их сохранение на своём устройстве, удалите уже имеющиеся файлы cookies через настройки браузера или прекратите использование сайта.

При отключении обработки cookie наш сайт продолжит функционировать, однако будут использоваться исключительно необходимые технические файлы, без которых работа ресурса невозможна.

Инструкция по отключению cookies
Принять
Настроить
Отклонить

ДОКУМЕНТАЦИЯ

Выберите версию, форк и язык для СУБД Digital Q.DataBase, чтобы прочитать или скачать всю документацию.
Техподдержка
Документация
Диасофт
Авторские права © 2016–2025 ООО "Диасофт Экосистема"
Скачать всю документацию:

5.2.1. Общие сведения о механизме работы триггеров

Триггер — это определение того, что база данных должна автоматически выполнять определенную функцию при совершении операции заданного типа. Триггеры могут быть определены для таблиц (как обычных, так и секционированных), представлений и сторонних таблиц.

Для таблиц и сторонних таблиц триггеры могут быть настроены на выполнение до или после любой операции INSERT, UPDATE, или DELETE операция, либо один раз для каждой измененной строки, либо один раз для SQL оператора. UPDATE триггеры также могут быть настроены на срабатывание только в том случае, если определенные столбцы указаны в SET предложение данного UPDATE оператора. Триггеры также могут срабатывать для TRUNCATE операторов. При возникновении триггерного события триггерная функция вызывается в соответствующее время для обработки данного события.

Для представлений триггеры могут быть определены для выполнения вместо INSERT, UPDATE, или DELETE операций. Такие INSTEAD OF триггеры срабатывают один раз для каждой строки, которую необходимо изменить в представлении. На триггерную функцию возлагается выполнение необходимых изменений в базовых таблицах, лежащих в основе представления, и, при необходимости, возврат измененной строки в том виде, в каком она должна отображаться в представлении. Триггеры для представлений также могут быть определены для выполнения один раз на SQL оператор, до или после INSERT, UPDATE, или DELETE операций. Однако такие триггеры срабатывают только в том случае, если также определен триггер INSTEAD OF для представления. В противном случае любой оператор, обращающийся к представлению, должен быть преобразован в оператор, затрагивающий соответствующие базовые таблицы; в этом случае будут срабатывать триггеры, связанные с базовыми таблицами.

Триггерная функция должна быть определена до того, как может быть создан сам триггер. Триггерная функция должна быть объявлена как функция, не принимающая аргументов и возвращающая тип триггер. (Триггерная функция получает входные данные через специальную структуру TriggerData структуре, а не в виде обычных аргументов функции.)

После создания подходящей триггерной функции триггер устанавливается с помощью CREATE TRIGGER. Одна и та же триггерная функция может использоваться для нескольких триггеров.

Digital Q.DataBase предлагает как построчные триггеры, так и операторные триггеры. При использовании построчного триггера триггерная функция вызывается один раз для каждой строки, затронутой оператором, вызвавшим срабатывание триггера. Напротив, операторный триггер вызывается только один раз при выполнении соответствующего оператора, независимо от количества строк, затронутых этим оператором. В частности, оператор, который не затрагивает ни одной строки, все равно приведет к выполнению всех применимых операторных триггеров. Эти два типа триггеров иногда называют триггерами уровня строки триггеры, так и триггерами уровня оператора триггеры соответственно. Триггеры для TRUNCATE могут быть определены только на уровне оператора, а не на уровне строк.

Триггеры также классифицируются в зависимости от момента их срабатывания: до, после, или вместо операции. Их называют соответственно BEFORE триггерами, AFTER триггерами и INSTEAD OF триггерами. Триггеры уровня оператора BEFORE срабатывают до того, как оператор начнет выполнение каких-либо действий, тогда как триггеры уровня оператора AFTER срабатывают в самом конце выполнения оператора. Эти типы триггеров могут быть определены для таблиц, представлений или сторонних таблиц. Триггеры уровня строки BEFORE срабатывают непосредственно перед выполнением операции над конкретной строкой, тогда как триггеры уровня строки AFTER срабатывают в конце выполнения оператора (но до срабатывания любых триггеров уровня AFTER оператора). Данные типы триггеров могут быть определены только для таблиц и сторонних таблиц, но не для представлений. INSTEAD OF триггеры могут быть определены только для представлений и только на уровне строк; они срабатывают немедленно, как только для каждой строки в представлении определяется необходимость выполнения операции.

Выполнение AFTER триггера может быть отложено до завершения транзакции, а не до завершения оператора, если он был определен как триггер ограничения. Во всех случаях триггер выполняется в рамках той же транзакции, что и вызвавший его оператор, поэтому, если оператор или триггер вызовут ошибку, результаты выполнения обоих будут откачены.

Если оператор INSERT содержит ON CONFLICT DO UPDATE предложение, возможно выполнение построчных BEFORE INSERT и последующих BEFORE UPDATE триггеров для задействованных строк. Подобные взаимодействия могут быть сложными, если триггеры не являются идемпотентными, так как изменения, внесенные BEFORE INSERT триггерами, будут видны BEFORE UPDATE триггерам, включая изменения в EXCLUDED столбцах.

Следует учитывать, что триггеры уровня оператора UPDATE триггеры выполняются, когда ON CONFLICT DO UPDATE указано, независимо от того, были ли затронуты какие-либо строки в результате UPDATE (и независимо от того, был ли выбран альтернативный UPDATE путь). Оператор INSERT с ON CONFLICT DO UPDATE предложением будет выполнять триггеры уровня оператора BEFORE INSERT сначала триггеры, затем триггеры уровня оператора BEFORE UPDATE триггеры, а затем триггеры уровня оператора AFTER UPDATE триггеры и, наконец, триггеры уровня оператора AFTER INSERT триггеры.

Оператор, обращающийся к родительской таблице в иерархии наследования или секционирования, не вызывает срабатывания триггеров уровня оператора затронутых дочерних таблиц; срабатывают только триггеры уровня оператора родительской таблицы. Однако триггеры уровня строки всех затронутых дочерних таблиц будут выполнены.

Если оператор UPDATE в секционированной таблице приводит к перемещению строки в другую секцию, это действие будет выполнено как DELETE из исходного раздела с последующей INSERT в новый раздел. В данном случае все триггеры уровня строки BEFORE UPDATE триггеры и все триггеры уровня строки BEFORE DELETE триггеры срабатывают в исходной секции. Затем все триггеры уровня строки BEFORE INSERT триггеры срабатывают в целевой секции. Следует учитывать возможность непредвиденных результатов, когда все эти триггеры влияют на перемещаемую строку. Что касается AFTER ROW триггеров, AFTER DELETE и AFTER INSERT триггеры применяются; но AFTER UPDATE триггеры не применяются, так как UPDATE была преобразована в DELETE и INSERT. Что касается триггеров уровня оператора, ни один из DELETE или INSERT триггеров не срабатывает, даже если происходит перемещение строки; только UPDATE триггеры, определенные для целевой таблицы, используемой в UPDATE операторе, будут запущены.

Отдельные триггеры не определяются для MERGE. Вместо этого, триггеры уровня оператора или уровня строки UPDATE, DELETE, и INSERT триггеры срабатывают в зависимости (для триггеров уровня оператора) от того, какие действия указаны в MERGE запросе, и (для триггеров уровня строки) того, какие действия фактически выполняются.

При выполнении MERGE команды триггеры уровня оператора BEFORE и AFTER триггеры срабатывают для событий, указанных в действиях MERGE команды, независимо от того, было ли действие в конечном итоге выполнено. Это аналогично оператору UPDATE , который не обновляет ни одной строки, но при этом триггеры уровня оператора срабатывают. Триггеры уровня строки срабатывают только тогда, когда строка действительно обновляется, вставляется или удаляется. Таким образом, вполне допустимо, что при срабатывании триггеров уровня оператора для определенных типов действий триггеры уровня строки для тех же типов действий не срабатывают.

Триггерные функции, вызываемые триггерами уровня оператора, всегда должны возвращать NULL. Триггерные функции, вызываемые триггерами уровня строки, могут возвращать строку таблицы (значение типа HeapTuple) вызывающему исполнителю, если это необходимо. Триггер уровня строки, срабатывающий перед выполнением операции, может действовать следующим образом:

  • Он может возвращать NULL для пропуска операции для текущей строки. Это указывает исполнителю не выполнять операцию уровня строки, вызвавшую триггер (вставку, изменение или удаление конкретной строки таблицы).

  • Только для триггеров уровня строки INSERT и UPDATE возвращаемая строка становится строкой, которая будет вставлена или заменит строку, подлежащую обновлению. Это позволяет триггерной функции изменять вставляемую или обновляемую строку.

Триггер уровня строки, BEFORE который не должен приводить к какому-либо из этих результатов, должен возвращать в качестве результата ту же строку, которая была передана (то есть NEW строку для INSERT и UPDATE триггеры, OLD строка для DELETE триггеры).

Триггер уровня строки INSTEAD OF триггерная функция должна либо возвращать NULL , сигнализируя о том, что она не изменяла данные в базовых таблицах представления, либо возвращать переданную строку представления ( NEW строку для INSERT и UPDATE операции, или OLD строка для DELETE операции). Ненулевое возвращаемое значение используется для подтверждения того, что триггер выполнил необходимые изменения данных в представлении. Это приведет к увеличению счетчика строк, затронутых командой. Только для INSERT и UPDATE операций триггер может изменить NEW строку перед её возвратом. Это изменит данные, возвращаемые INSERT RETURNING или UPDATE RETURNING, что полезно в тех случаях, когда представление не будет отображать в точности те же данные, которые были предоставлены.

Возвращаемое значение игнорируется для триггеров уровня строки, вызываемых после операции, поэтому они могут возвращать NULL.

В отношении генерируемых столбцов действуют некоторые особенности. Хранимые генерируемые столбцы вычисляются после BEFORE триггеров и перед AFTER триггерами. Следовательно, сгенерированное значение можно проверить в AFTER триггерах. В BEFORE триггеры, OLD строка содержит старое сгенерированное значение, как и ожидалось, но NEW строка еще не содержит нового сгенерированного значения, и обращаться к ней не следует. В интерфейсе на языке C содержимое столбца в данный момент не определено; язык программирования более высокого уровня должен предотвращать доступ к хранимому генерируемому столбцу в NEW строке в BEFORE триггере. Изменения значения генерируемого столбца в BEFORE триггере игнорируются и будут перезаписаны.

Если для одного и того же события в одном и том же отношении определено несколько триггеров, они будут срабатывать в алфавитном порядке их имен. В случае BEFORE и INSTEAD OF триггеров: строка, возвращаемая каждым триггером (которая может быть изменена), становится входными данными для следующего триггера. Если какой-либо BEFORE или INSTEAD OF триггер возвращает NULL, выполнение операции для этой строки прекращается, и последующие триггеры (для этой строки) не срабатывают.

В определении триггера также можно указать логическое WHEN условие, которое проверяется для определения необходимости вызова триггера. В триггерах уровня строки WHEN условие может проверять старые и/или новые значения столбцов строки. (Триггеры уровня оператора также могут иметь WHEN условия, хотя эта функциональность для них менее полезна.) В BEFORE триггере WHEN условие вычисляется непосредственно перед выполнением функции (или моментом её возможного выполнения), поэтому использование WHEN существенно не отличается от проверки того же условия в начале триггерной функции. Однако в AFTER триггере WHEN условие вычисляется сразу после обновления строки и определяет, будет ли событие поставлено в очередь для вызова триггера в конце выполнения оператора. Таким образом, когда AFTER триггера WHEN условие не возвращает true, отсутствует необходимость как в постановке события в очередь, так и в повторном извлечении строки в конце выполнения оператора. Это может привести к значительному ускорению операторов, изменяющих большое количество строк, если триггер должен срабатывать только для некоторых из них. INSTEAD OF триггеры не поддерживают WHEN условия.

Как правило, триггеры уровня BEFORE строки используются для проверки или изменения данных, подлежащих вставке или обновлению. Например, BEFORE триггер может применяться для вставки текущего времени в timestamp столбец или для проверки согласованности двух элементов строки. Триггеры уровня AFTER строки наиболее целесообразно использовать для распространения обновлений на другие таблицы или для выполнения проверок согласованности по другим таблицам. Причина такого разделения функций заключается в том, что AFTER триггер гарантированно видит окончательное значение строки, в то время как BEFORE триггер не может; могут быть другие BEFORE триггеры, срабатывающие после него. Если нет веских оснований создавать триггер BEFORE или AFTER, то BEFORE вариант более эффективен, так как информация об операции не должна сохраняться до завершения инструкции.

Если триггерная функция выполняет SQL-команды, то эти команды могут снова вызвать срабатывание триггеров. Это явление называется каскадным срабатыванием триггеров. Прямых ограничений на количество уровней каскадности не существует. Каскадное выполнение может привести к рекурсивному вызову того же триггера; например, INSERT триггер может выполнить команду, которая вставляет дополнительную строку в ту же таблицу, что приведет к INSERT повторному срабатыванию триггера. Ответственность за предотвращение бесконечной рекурсии в таких сценариях лежит на разработчике триггера.

Если ограничение внешнего ключа определяет ссылочные действия (то есть каскадные обновления или удаления), эти действия выполняются с помощью обычных SQL-команд UPDATE или DELETE для ссылающейся таблицы. В частности, при таких изменениях будут срабатывать любые триггеры, существующие для ссылающейся таблицы. Если такой триггер изменяет или блокирует действие одной из этих команд, это может привести к нарушению ссылочной целостности. Ответственность за предотвращение подобных ситуаций возлагается на разработчика триггера.

При определении триггера для него могут быть указаны аргументы. Использование аргументов в определении триггера позволяет различным триггерам со схожими требованиями вызывать одну и ту же функцию. В качестве примера можно привести универсальную триггерную функцию, которая принимает в качестве аргументов имена двух столбцов и записывает имя текущего пользователя в один из них, а текущую метку времени — в другой. При правильной реализации такая триггерная функция не будет зависеть от конкретной таблицы, для которой она срабатывает. Таким образом, эту же функцию можно использовать для INSERT событий в любой таблице с подходящими столбцами, например, для автоматического отслеживания создания записей в таблице транзакций. Её также можно использовать для отслеживания событий последнего обновления, если она определена как UPDATE триггер.

В каждом языке программирования, поддерживающем триггеры, предусмотрен собственный метод передачи входных данных триггера триггерной функции. Эти входные данные включают тип события триггера (например, INSERT или UPDATE), а также любые аргументы, указанные в CREATE TRIGGER. Для триггера уровня строки входные данные также включают NEW строку для INSERT и UPDATE триггеров и/или OLD строку для UPDATE и DELETE триггеров.

По умолчанию в триггерах уровня оператора отсутствует возможность анализа отдельных строк, измененных оператором. Однако AFTER STATEMENT триггер может инициировать создание переходных таблиц, чтобы сделать наборы измененных строк доступными для триггера. AFTER ROW триггеры также могут запрашивать переходные таблицы, что позволяет им видеть как общие изменения в таблице, так и изменения в конкретной строке, для которой они вызваны в данный момент. Метод обращения к переходным таблицам также зависит от используемого языка программирования, но стандартный подход заключается в том, что переходные таблицы функционируют как временные таблицы только для чтения, к которым можно обращаться с помощью SQL-команды, вызываемых внутри триггерной функции.

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

*поля обязательные к заполнению