Триггер ABL – это блок ABL кода, который выполняется всякий раз, когда происходит определенное событие базы данных. Событие базы данных – это действие, выполненное против базы данных. Например, когда Вы выполняете запись в базу данных - происходит событие WRITE.
Поскольку триггеры базы данных выполняются всякий раз, когда происходит событие базы данных, они полезны для таких задач, как обеспечение ссылочной целостности данных. Например, если Вы удаляете запись о клиенте из базы данных, то Вы также должны удалить записи обо всех заказах этого клиента. Событие удаления клиентской записи инициализирует задачу по удалению всех ассоциированных с клиентом заказах. Триггер базы данных идеален для такого типа обработки, потому что такие задачи должны всегда выполняться, когда происходит какое-либо специфическое событие. Другие задачи, которые они могут выполнять, это обеспечение безопасности базы данных или запись аудиторского следа.
Для получения дополнительной информации об использовании ABL для написания кода триггеров, см. OpenEdge Development: ABL Reference и OpenEdge Development: ABL Handbook.
ABL события базы данных
Триггеры базы данных обеспечивают связь таблиц или полей с событиями базы данных. Когда происходит событие - выполняется триггер. ABL не обеспечивает поддержку событий для всех действий в базе данных. Например, хоть Вы и можете выполнить выгрузку (dump) данных из базы, Вы не сможете написать триггер для события DUMP, потому что ABL не поддерживает такое событие.
Однако ABL в дополнение к стандартным триггерам, для определенных событий поддерживает триггеры, связанные с репликацией. Репликационные триггеры помогают Вам осуществлять репликацию баз данных. Для получения дополнительной информации по ним, см. OpenEdge Development: ABL Handbook.
События базы данных, которые поддерживает ABL, следующие:
- CREATE. Когда виртуальная машина ABL (AVM) выполняет операторы CREATE или INSERT для таблицы базы данных, AVM создает запись, затем запускает все соответствующие CREATE-триггеры, и затем запускает все соответствующие REPLICATION-CREATE триггеры.
- DELETE. Когда AVM выполняет оператор DELETE для таблицы базы данных, AVM запускает все соответствующие DELETE триггеры, затем запускает все соответствующие REPLICATION-DELETE триггеры, далее проверяет правильность удаления, и только потом выполняет само удаление.
- FIND. Когда AVM читает запись из таблицы базы данных, используя операторы FIND, GET или цикл FOR EACH, он запускает все соответствующие FIND триггеры. FIND триггеры срабатывают только для записей, которые полностью удовлетворяют всем условиям поиска, таким которые определяются в выражении WHERE. FIND триггеры не срабатывают в ответ на работу функции CAN-FIND. Примечание: если произошел сбои FIND триггера, AVM ведет себя так, как если бы запись не соответствовала критериям поиска. Если FIND был в пределах блока FOR EACH, то AVM просто переходит к следующей записи.
- WRITE. Когда AVM изменяет содержимое записи и проверяет ее правильность для таблицы базы данных, AVM сначала запускает соответствующие WRITE триггеры, затем запускает все соответствующие REPLICATION-WRITE триггеры. Когда изменение завершено, AVM автоматически проверяет правильность записи. Вы можете также использовать оператор VALIDATE, чтобы явно проверить правильность записи. В любом случае WRITE триггеры выполняются прежде, чем происходит проверка правильности (таким образом, WRITE триггеры могут исправить значение и сделать более сложную проверку правильности). Если проверка записи выполняется много раз, и вы выполняете изменения записи в промежутке между этими проверками, то AVM может не раз выполнять WRITE триггеры для такой записи прежде, чем он запишет ее в базу данных, т.к. модификацией считается любое изменение, даже если Вы возвращаете исходное значение.
- ASSIGN. Когда AVM обновляет поле в базе данных, то он запускает все связанные ASSIGN триггеры. В отличие от других событий базы данных, это событие выполняет мониторинг определенного поля, а не таблицы. ASSIGN триггеры, выполняются, когда содержимое ассоциированного поля изменилось. Процедура триггера выполняется в конце оператора, который устанавливает новое значение полю, и после любой возможной переиндексации. Если оператор содержит несколько полей для изменения (например, UPDATE name city street), то AVM запускает каждый соответствующий ASSIGN триггер в конце оператора. Если произойдет сбой в каком-нибудь триггере, то AVM отменит все изменения оператора (если, конечно же, у него нет опции NO-UNDO).
Триггеры схемы и сессий
ABL поддерживает два типа триггеров базы данных: для схемы и для сессий. Триггер схемы – это “.p” процедура, которую Вы добавляете, через Data Dictionary к схеме базы данных. Код триггера схемы, определенный в базе данных, выполняется клиентами базы данных.
Триггер сессии – это часть кода, который Вы добавляете в состав другой процедуры.
Триггеры схемы
Вы можете создавать триггеры схемы через диалоговое окно Table или Field Properties в Data Dictionary. Когда Вы используете Data Dictionary чтобы определить триггер схемы для таблицы или поля, то триггер автоматически добавляется к таблице или определениям данных конкретного поля. OpenEdge позволяет определять триггер в то время, когда Вы создаете или изменяете таблицу или поле. Это определение триггера сохраняется в триггерной процедуре. За информацией относительно использования Data Dictionary для создания и удаления триггеров, см. OpenEdge Development: Basic Database Tools (для CHUI) и в графическом интерфейсе, интерактивной справки для Data Dictionary. Для получения дополнительной информации о триггерах схемы, см. OpenEdge Development: ABL Handbook.
Различия между триггерами схемы и триггерами сессий
Хотя их синтаксис является немного различным, триггеры схемы и сессий обеспечивают одинаковую функциональность. Важное различие между ними - то, что триггеры схемы – это независимые процедуры; тогда как триггеры сессий содержатся в пределах другой процедуры. Из-за этого различия триггеры схемы выполняются всегда, когда происходит указанное событие, независимо от того, какое приложение инициализирует это событие.
Триггеры сессий определены как часть специфического приложения и действуют только в пределах этого специфического приложения. Так как триггеры сессий выполняются изнутри процедуры, в которую они включены, у них есть доступ к фреймам, виджетам, и переменным, определенным в этой процедуре.
Так как триггеры схемы откомпилированы отдельно от процедуры, которая инициализирует их выполнение, у них нет доступа к фреймам процедуры, ее виджетам и переменным. Используйте триггеры схемы для того, чтобы обрабатывать специфические события. Например, когда запись о заказе (order) удаляется, Вы всегда должны удалять связанные с заказом записи о его содержимом (order-lines).
Используйте триггеры сессий, чтобы выполнять дополнительную или независимую обработку, когда происходит событие. Оба типа триггеров проверяют возвращаемые состояния ERROR, тем самым заставляя ассоциированное событие реагировать на ошибки соответствующим образом. Для получения дополнительной информации об опции ERROR оператора RETURN, см. OpenEdge Development: ABL Reference.
Взаимодействие триггеров
Вы можете определить триггер схемы и триггер сессии для одного и того же события одной таблицы и поля. То, как триггеры станут взаимодействовать, будет зависеть от того, как Вы их определите.
Обычно, выполняются оба триггера, но триггер сессии выполняется первым (за исключением FIND триггера сессии, который выполняется после FIND триггера схемы). Таким образом, у триггера схемы всегда есть приоритет над триггером сессии. Для WRITE, DELETE, CREATE, или ASSIGN события, триггер схемы может отменить триггер сессии. Для события FIND, триггер схемы может захватить триггер сессии.
Практические советы по использованию ABL триггеров
Когда Вы пишете ABL триггеры, существует несколько общих моментов, которые Вы должны иметь в виду.
Таблицы метасхемы
ABL не поддерживает триггеры базы данных на события для таблиц и полей метасхемы. Это таблицы или поля, названия которых начинаются с символа подчеркивания. Вы можете обрабатывать события базы данных только для прикладных объектов базы данных.
Кодирование взаимодействий с пользователем
ABL позволяет использовать любой тип оператора ABL в пределах триггерного блока, включая те, которые используются для взаимодействия с пользователем. Однако, не рекомендуется включать в него операторы, которые запрашивают ввод от пользователя.
Например, если пользователь выполняет процедуру в пакетном режиме, триггер с таким запросом заставит процедуру остановиться, ожидая пользовательского ввода.
Триггеры могут запускать другие триггеры
Действие в пределах одной триггерной процедуры может выполнить другую триггерную процедуру. Например, если триггерная процедура изменяет значение поля, и Вы определили ASSIGN триггер для того поля, то этот триггер будет выполнен. Вы должны тщательно проектировать свои триггеры, чтобы избежать конфликтов. Например, триггер A мог изменить данные, которые могли заставить триггер B выполняться. Триггер B мог изменить те же самые данные, изменение которых Вы не ожидали или не хотели.
Триггеры могут запускать транзакции
По своей природе, CREATE, DELETE, WRITE, и ASSIGN триггеры, выполняются изнутри транзакции. Т.к. само событие вызова должно происходить в пределах транзакции.
Это означает, что, в это время Вы можете запустить субтранзакцию в пределах триггерной процедуры для этих событий. Но вы не можете запустить новую транзакцию. Однако FIND может выполняться и не из транзакции. Поэтому, Вы не можете запустить субтранзакцию в пределах FIND триггера; она может оказаться завершенной транзакцией.
Где выполняются триггеры
Триггеры базы данных (включая репликационные триггеры) выполняются в прикладной логике, которая состоит из серверов приложений OpenEdge и локальных ABL процедур. Для получения дополнительной информации по серверам приложений OpenEdge, см. OpenEdge Application Server: Developing AppServer Applications.
Сохранение триггерных процедур
Вы можете сохранить триггерные процедуры базы данных в каталоге операционной системы или в r-кодовой библиотеке ABL.
Взаимодействие с SQL
Из-за врожденных различий между ABL и SQL, триггеры не могут выполниться точно таким же способом. Для получения дополнительной информации о том, как SQL и триггеры базы данных взаимодействуют, см. OpenEdge Data Management: SQL Reference.
Применяются следующие правила:
- Триггеры SQL не будут срабатывать, когда происходят ABL события.
- Триггеры ABL не будут срабатывать, когда происходят SQL события.
- Чтобы гарантировать целостность, Вы должны иметь оба типа триггеров. Или использовать SQL только, чтобы читать данные. Или же иметь только SQL таблицы.