В прошлой статье мы рассказали о триггерах и о том, как они могут помочь автоматизировать рутинные операции менеджера.
Сейчас мы рассмотрим, как это реально работает в программе. Для этого мы настроили этапы продаж для одного бизнес-процесса и для каждого из них -триггеры.
Наша организация ООО Ромашка работает по следующему сценарию:
Менеджер проводит холодный обзвон по клиентской базе. При выявлении интереса клиенту отправляется письмо с информацией о компании и об услугах. На следующий день менеджер перезванивает клиенту, выявляет потребность и после готовит КП. При формировании предложения на сумму более 100000 рублей нужно уведомить руководителя.
После отправки КП клиент принимает решение, и менеджер оформляет договор и счет, отправляет покупателю. После этого необходимо проконтролировать оплату и оформить отгрузку.
Работа ведется в программе «1С:CRM3.0», для которой настроен обмен данными с «1С:Бухгалтерия предприятия 8».
Этапы бизнес-процесса выглядят так:
Триггеры продаж в маркетинге! / Лучшие триггеры, которые используют при продажах
1. Отправка информационного письма;
2. Подготовка предложения/КП;
5. Интерес закрыт (потерян).
В программе этапы продаж с настроенными триггерами выглядят так (рис. 1):
Этап 1. Отправка информационного письма
Менеджер проводит холодный обзвон по клиентской базе. При выявлении потребности у клиента создает сделку (Интерес). При попадании сделки на первый этап автоматически формируется по шаблону и отправляется информационное письмо клиенту.
Триггер формирует задачу менеджеру «Перезвонить клиенту» с целью уточнения, получил ли клиент письмо и организации дальнейшей работы (рис. 3). При необходимости можно вручную откорректировать дату следующего звонка.
Этап 2. Формирование коммерческого предложения
В день, когда запланирован звонок, на рабочем столе менеджера появляется информация о запланированном взаимодействии. Менеджер перезванивает клиенту, уточняет запрос и формирует коммерческое предложение. При проведении документа «Коммерческое предложение» в программе триггеры пересчитывают потенциальную выручку (рис.
4), отправляют письмо руководителю (т.к. у нас сумма документа больше 100 000 рублей) (рис. 5), переводят интерес на следующий этап (рис. 6), формируют задачу нашему менеджеру -планируют следующий звонок (рис.7).
В случае отсутствия триггеров, менеджеру пришлось бы вручную сформировать письмо, прикрепить к нему файлы, отправить его, сформировать себе задачу, проинформировать руководителя о коммерческом предложении на сумму более 100 тыс., перезаполнить потенциальную выручку, перевести интерес на следующий этап.
Этап 3. Контроль получения КП клиентом. Выставление счета.
Менеджер перезванивает по запланированной задаче клиенту. Клиент просит выставить счет. Менеджер на основании коммерческого предложения в один клик формирует счет на оплату. Отправляет его по почте. Триггеры автоматически переводят интерес на этап «Счет» (рис.
8), формируют задачу менеджеру (рис. 9).
Последовательные логические устройства. Триггеры (RS, D, JK, T). Принцип работы, типовые схемы.
Этапы 4,5,6. Счет, Отгрузка, закрытие интереса.
Как было уже сказано выше, у нашей гипотетической организации настроен обмен между «1С:Бухгалтерия предприятия» и «1С:CRM». Сформированный Счет на оплату из CRM попадает в Бухгалтерию.
Бухгалтер отражает оплату и отгрузку в «Бухгалтерии предприятия». Информация об этом через обмен данными попадает в «1С:CRM». Триггеры автоматически завершат интерес, переведя его в состояние «Завершено успешно» (рис.10).
Такая настройка этапов продаж и автоматизация её триггерами, во-первых, сокращает рутинные операции, во-вторых, облегчает работу менеджеров, тем самым освобождая им время для других задач.
Исключается и влияние человеческого фактора в части действий менеджера при работе с клиентами. Программа предотвратит такие проблемы, как:
1) Забыли вовремя отправить клиенту информационное письмо, КП, Счет на оплату. Забыли проконтролировать получение клиентом последних;
2) Забыли проинформировать руководителя о какой-либо информации о сделке;
3) Не изменили этап сделки;
Также триггеры сводят на нет случаи, когда менеджер работает по интересу, еще не запланировал следующее взаимодействие, а программа аварийно завершила работу программы по тем или иным причинам. Триггеры в любом случаю создадут взаимодействие и клиент не останется без внимания.
Использование механизмов триггеров позволяет сократить время работы пользователей с программой, уменьшить количество ошибок при вводе данных, обеспечить соблюдение регламентов по работе с программой.
Хотите автоматизировать продажи, навести порядок, исключить человеческий фактор и увеличить прибыль компании?
Запишитесь на бесплатную демонстрацию программы 1С:CRM!
Источник: dzen.ru
Триггеры
Триггеры многоплатформенного пользовательского интерфейса приложения .NET (.NET MAUI) позволяют декларативно выражать действия в XAML, изменяющие внешний вид элементов управления на основе событий или изменений данных. Кроме того, триггеры состояния, которые относятся к специализированной группе триггеров, определяют, когда следует применять VisualState.
Триггер можно назначить непосредственно коллекции элемента управления Triggers или добавить его в словарь ресурсов на уровне страницы или приложения для применения к нескольким элементам управления.
Триггеры свойств
Представляет Trigger триггер, который применяет значения свойств или выполняет действия, когда указанное свойство соответствует указанному условию.
В следующем примере показан объект , Trigger который изменяет цвет фона Entry при получении фокуса:
В объявлении триггера указывается следующее:
- TargetType — тип элемента управления, к которому применяется триггер.
- Property — свойство отслеживаемого элемента управления.
- Value — значение, возникающее для отслеживаемого свойства, которое приводит к активации триггера.
- Setter — коллекция Setter элементов, которые применяются при выполнении условия триггера.
Кроме того, можно указать необязательные EnterActions коллекции и ExitActions . Дополнительные сведения см. в разделах EnterActions и ExitActions.
Применение триггера с помощью стиля
Триггеры также можно добавлять в объявление Style в элементе управления в ResourceDictionary на странице или в приложении. В следующем примере объявляется неявный стиль для всех Entry элементов управления на странице:
Триггеры данных
Представляет DataTrigger триггер, который применяет значения свойств или выполняет действия, когда привязанные данные соответствуют указанному условию. Расширение Binding разметки используется для отслеживания указанного условия.
В следующем примере показан объект , DataTrigger который отключает , Button если Entry объект пуст:
, Path=Text.Length>» Value=»0″>
В этом примере, если длина равна нулю Entry , активируется триггер.
При оценке Path=Text.Length всегда укажите значение по умолчанию для целевого свойства (например, Text=»» ), так как в противном случае он будет null иметь значение и триггер не будет работать так, как вы ожидаете.
Кроме того, можно указать необязательные EnterActions коллекции и ExitActions . Дополнительные сведения см. в разделах EnterActions и ExitActions.
Триггеры событий
Представляет EventTrigger триггер, который применяет набор действий в ответ на событие. В отличие от Trigger, EventTrigger не имеет понятия завершения состояния, поэтому действия не будут отменены, когда условие, вызвавщее событие, больше не будет истинным.
Требуется EventTrigger задать только Event свойство :
В этом примере элементы отсутствуют Setter . Вместо этого есть NumericalValidationTriggerAction объект .
Триггеры событий не поддерживают EnterActions и ExitActions.
Реализация действия триггера должна:
- Реализация универсального класса TriggerAction с универсальным параметром, соответствующим типу элемента управления, к которому будет применяться триггер. Вы можете использовать классы, VisualElement например , для записи действий триггера, которые работают с различными элементами управления, или указать тип элемента управления, например Entry.
- Переопределите метод Invoke . Этот метод вызывается при каждом возникновении события триггера.
- При необходимости можно предоставить свойства, которые можно задать в XAML при объявлении триггера.
В следующем примере показан NumericValidationTriggerAction класс :
public class NumericValidationTriggerAction : TriggerAction < protected override void Invoke(Entry entry) < double result; bool isValid = Double.TryParse(entry.Text, out result); entry.TextColor = isValid ? Colors.Black : Colors.Red; >>
Будьте внимательны при совместном использовании триггеров в ResourceDictionary. Один экземпляр будет совместно использоваться элементами управления, поэтому любое состояние, настроенное один раз, будет применяться ко всем элементам управления.
Несколько триггеров
Представляет MultiTrigger триггер, который применяет значения свойств или выполняет действия при выполнении набора условий. Перед применением Setter объектов все условия должны быть истинными.
В следующем примере показан объект , MultiTrigger который привязывается к двум Entry объектам:
, Path=Text.Length>» Value=»0″ /> , Path=Text.Length>» Value=»0″ />
Кроме того, MultiTrigger.Conditions коллекция может также содержать PropertyCondition объекты :
EnterActions и ExitActions
Альтернативным подходом к реализации изменений при возникновении триггера является указание EnterActions коллекций и ExitActions , а также создание TriggerAction реализаций.
Коллекция EnterActions типа IList определяет коллекцию, которая будет вызываться при выполнении условия триггера. Коллекция ExitActions типа IList определяет коллекцию, которая будет вызываться после того, как условие триггера больше не выполняется.
Объекты TriggerAction, определенные в коллекциях EnterActions и ExitActions, игнорируются классом EventTrigger.
В следующем примере показан триггер свойства, указывающий EnterAction и ExitAction :
Реализация действия триггера должна:
- Реализация универсального класса TriggerAction с универсальным параметром, соответствующим типу элемента управления, к которому будет применяться триггер. Вы можете использовать классы, VisualElement например , для записи действий триггера, которые работают с различными элементами управления, или указать тип элемента управления, например Entry.
- Переопределите метод Invoke . Этот метод вызывается при каждом возникновении события триггера.
- При необходимости можно предоставить свойства, которые можно задать в XAML при объявлении триггера.
В следующем примере показан FadeTriggerAction класс :
public class FadeTriggerAction : TriggerAction < public int StartsFrom < get; set; >protected override void Invoke(VisualElement sender) < sender.Animate(«FadeTriggerAction», new Animation((d) =>< var val = StartsFrom == 1 ? d : 1 — d; sender.BackgroundColor = Color.FromRgb(1, val, 1); >), length: 1000, // milliseconds easing: Easing.Linear); > >
Можно указать EnterActions объекты и , ExitActions а также Setter в триггере, но имейте в виду, что Setter объекты вызываются немедленно (они не ожидают EnterAction завершения или ExitAction ).
Триггеры состояния
Триггеры состояния — это специализированная группа триггеров, определяющих условия применения VisualState.
Триггеры состояния добавляются в коллекцию StateTriggersVisualState. Эта коллекция может содержать один или несколько триггеров состояния. При наличии активных триггеров состояния в коллекции будет применяться VisualState.
При использовании триггеров состояния для управления визуальными состояниями .NET MAUI использует следующие правила приоритета, чтобы определить, какой триггер (и соответствующий VisualState) будет активен:
- Любой триггер, производный от StateTriggerBase.
- AdaptiveTrigger активируется из-за выполнения условия MinWindowWidth.
- AdaptiveTrigger активируется из-за выполнения условия MinWindowHeight.
Если одновременно активны несколько триггеров (например, два пользовательских триггера), то у первого триггера, объявленного в разметке, будет приоритет.
Триггеры состояния можно задать в Style или напрямую в элементах.
Дополнительные сведения о визуальных состояниях см. в разделе Визуальные состояния.
Триггер состояния
Класс StateTrigger, производный от класса StateTriggerBase, имеет привязываемое свойство IsActive. StateTrigger выполняет изменение VisualState, когда свойство IsActive изменяет значение.
Класс StateTriggerBase, который является базовым классом для всех триггеров состояния, имеет свойство IsActive и событие IsActiveChanged. Это событие возникает при каждом изменении VisualState. Кроме того, класс StateTriggerBase имеет переопределяемые методы OnAttached и OnDetached.
Привязываемое свойство StateTrigger.IsActive скрывает унаследованное свойство StateTriggerBase.IsActive .
В следующем примере XAML показан элемент Style, предусматривающий объекты StateTrigger:
» IsActiveChanged=»OnCheckedStateIsActiveChanged» /> >» IsActiveChanged=»OnUncheckedStateIsActiveChanged» />
В этом примере неявный элемент Style направлен на объекты Grid. Если у свойства IsToggled привязанного объекта значение true , цвет фона Grid задается черным. Когда у свойства IsToggled привязанного объекта значение false , активируется изменение VisualState, а цвет фона Grid становится белым.
Кроме того, при каждом VisualState изменении IsActiveChanged вызывается событие для VisualState . Каждый элемент VisualState регистрирует обработчик событий для этого события:
void OnCheckedStateIsActiveChanged(object sender, EventArgs e) < StateTriggerBase stateTrigger = sender as StateTriggerBase; Console.WriteLine($»Checked state active: «); > void OnUncheckedStateIsActiveChanged(object sender, EventArgs e) < StateTriggerBase stateTrigger = sender as StateTriggerBase; Console.WriteLine($»Unchecked state active: «); >
В этом примере при возникновении обработчика IsActiveChanged для события обработчик выводит, активен ли VisualState объект . Например, следующие сообщения выводятся в окно консоли при переходе от визуального состояния Checked к визуальному состоянию Unchecked :
Checked state active: False Unchecked state active: True
Триггеры настраиваемого состояния могут быть созданы путем наследования от класса StateTriggerBase и переопределения методов OnAttached и OnDetached для выполнения необходимых операций регистраций и очистки.
Адаптивный триггер
AdaptiveTrigger активирует изменение VisualState, когда окно имеет заданную высоту или ширину. Этот триггер имеет два привязываемых свойства:
- MinWindowHeight типа double , которое указывает минимальную высоту окна, при которой следует применять VisualState.
- MinWindowWidth типа double , которое указывает минимальную ширину окна, при которой следует применять VisualState.
AdaptiveTrigger является производным от класса StateTriggerBase и может присоединить обработчик событий к событию IsActiveChanged .
В следующем примере XAML показан элемент Style, предусматривающий объекты AdaptiveTrigger:
В этом примере неявный элемент Style направлен на объекты StackLayout. Если ширина окна — 0–800 аппаратно-независимых единиц, у объектов StackLayout, к которым применяется Style, будет вертикальная ориентация. Если ширина окна = >800 единиц, независимых от устройства, VisualState активируется изменение, а ориентация StackLayout меняется на горизонтальную.
Свойства MinWindowHeight и MinWindowWidth можно использовать независимо друг от друга или совместно. Ниже представлен простой пример XAML для установки обоих свойств:
В этом примере указывает, что соответствующий AdaptiveTriggerVisualState элемент будет применяться, если текущая ширина окна = >800 независимых от устройств единиц, а текущая высота окна = >1200 единиц, независимых от устройства.
Сравнение триггера состояния
CompareStateTrigger активирует изменение VisualState, если свойство равно определенному значению. Этот триггер имеет два привязываемых свойства:
- Property типа object указывает свойство, сравниваемое триггером.
- Value типа object указывает значение, при котором следует применить VisualState.
CompareStateTrigger является производным от класса StateTriggerBase и может присоединить обработчик событий к событию IsActiveChanged .
В следующем примере XAML показан элемент Style, предусматривающий объекты CompareStateTrigger:
, Path=IsChecked>» Value=»True» /> , Path=IsChecked>» Value=»False» /> .
В этом примере неявный элемент Style направлен на объекты Grid. Если у свойства IsChecked CheckBox значение false , устанавливается белый цвет фона Grid. CheckBox.IsChecked Когда свойство становится true , VisualState активируется изменение, а цвет фона становится чернымGrid.
Триггер состояния устройства
DeviceStateTrigger активирует изменение VisualState в зависимости от платформы устройства, на которой работает приложение. У этого триггера одно привязываемое свойство:
- Device типа string указывает платформу устройства, на которой следует применить VisualState.
DeviceStateTrigger является производным от класса StateTriggerBase и может присоединить обработчик событий к событию IsActiveChanged .
В следующем примере XAML показан элемент Style, предусматривающий объекты DeviceStateTrigger:
В этом примере явный элемент Style направлен на объекты ContentPage. ContentPage Объекты, использующие стиль, задают для своего фона серебристый цвет в iOS и бледно-синий в Android.
Триггер состояния ориентации
OrientationStateTrigger активирует изменение VisualState при изменении ориентации устройства. У этого триггера одно привязываемое свойство:
- Orientation типа DisplayOrientation указывает ориентацию, к которой следует применять VisualState.
OrientationStateTrigger является производным от класса StateTriggerBase и может присоединить обработчик событий к событию IsActiveChanged .
В следующем примере XAML показан элемент Style, предусматривающий объекты OrientationStateTrigger:
В этом примере явный элемент Style направлен на объекты ContentPage. Объекты ContentPage, использующие этот стиль, устанавливают серебристый цвет фона, если ориентация книжная, и белый — если ориентация альбомная.
Источник: learn.microsoft.com
Общие сведения о триггерах
где plsql_trigger_source, это такая конструкция:
Конструкции simple_dml_trigger, instead_of_dml_trigger, compound_dml_trigger и system_trigger будут приведены в соответствующих разделах статьи.
DML triggers
- DML триггеры создаются для таблиц или представлений, срабатывают при вставке, обновлении или удалении записей.
- Триггер может быть создан в другой схеме, отличной от той, где определена таблицы. В таком случае текущей схемой при выполнении триггера считается схема самого триггера.
- При операции MERGE срабатывают триггеры на изменение, вставку или удаление записей в зависимости от операции со строкой.
- Триггер – часть транзакции, ошибка в триггере откатывает операцию, изменения таблиц в триггере становятся частью транзакции.
- Если откатывается транзакция, изменения триггера тоже откатываются.
- В триггерах запрещены операторы DDL и управления транзакциями (исключения – автономные транзакции).
Конструкция simple_dml_trigger:
Где, dml_event_clause:
referencing_clause:
trigger_edition_clause:
trigger_body:
- На таблице
- На представлении (instead of trigger)
- Вставка записей (insert)
- Обновление записей (update)
- Удаление записей (delete)
- Уровень всей команды (statement level triggers)
- Уровень записи (row level triggers)
- Составные триггеры (compound triggers)
- Перед выполнением операции (before)
- После выполнения операции (after)
Crossedition triggers — служат для межредакционного взаимодействия, например для переноса и трансформации данных из полей, отсутствующих в новой редакции, в другие поля.
Условные предикаты для определения операции, на которую сработал триггер:
Inserting | True, если триггер сработал на операцию Insert |
Updating | True, если триггер сработал на операцию Update |
Updating(‘colum’) | True, если триггер сработал на операцию Update, которая затрагивает определенное поле |
Deleting | True, если триггер сработал на операцию Delete |
Эти предикаты могут использоваться везде, где можно использовать Boolean выражения.
Пример
CREATE OR REPLACE TRIGGER t BEFORE INSERT OR UPDATE OF salary, department_id OR DELETE ON employees BEGIN CASE WHEN INSERTING THEN DBMS_OUTPUT.PUT_LINE(‘Inserting’); WHEN UPDATING(‘salary’) THEN DBMS_OUTPUT.PUT_LINE(‘Updating salary’); WHEN UPDATING(‘department_id’) THEN DBMS_OUTPUT.PUT_LINE(‘Updating department ID’); WHEN DELETING THEN DBMS_OUTPUT.PUT_LINE(‘Deleting’); END CASE; END;
Псевдозаписи
Существуют псевдозаписи, позволяющие обратиться к полям изменяемой записи и получить значения полей до изменения и значения полей после изменения. Это записи old и new. С помощью конструкции Referencing можно изменить их имена. Структура этих записей tablename%rowtype. Эти записи есть только у триггеров row level или у compound триггеров (с секциями уровня записи).
Insert | Null | Новое значение |
Update | Старое значение | Новое значение |
Delete | Старое значение | Null |
- С псевдозаписями запрещены операции уровня всей записи ( :new = null;)
- Нельзя изменять значения полей записи old
- Если триггер срабатывает на delete, нельзя изменить значения полей записи new
- В триггере after нельзя изменить значения полей записи new
Instead of dml triggers
- Создаются для представлений (view) и служат для замещения DML операций своим функционалом.
- Позволяют производить операции вставки/обновления или удаления для необновляемых представлений.
Конструкция instead_of_dml_trigger:
- Это всегда триггер уровня записи (row level)
- Имеет доступ к псевдозаписям old и new, но не может изменять их
- Заменяет собой dml операцию с представлением (view)
Пример
CREATE OR REPLACE VIEW order_info AS SELECT c.customer_id, c.cust_last_name, c.cust_first_name, o.order_id, o.order_date, o.order_status FROM customers c, orders o WHERE c.customer_id = o.customer_id; CREATE OR REPLACE TRIGGER order_info_insert INSTEAD OF INSERT ON order_info DECLARE duplicate_info EXCEPTION; PRAGMA EXCEPTION_INIT (duplicate_info, -00001); BEGIN INSERT INTO customers (customer_id, cust_last_name, cust_first_name) VALUES ( :new.customer_id, :new.cust_last_name, :new.cust_first_name); INSERT INTO orders (order_id, order_date, customer_id) VALUES ( :new.order_id, :new.order_date, :new.customer_id); EXCEPTION WHEN duplicate_info THEN RAISE_APPLICATION_ERROR ( num=> -20107, msg=> ‘Duplicate customer or order ID’); END order_info_insert;
Instead of triggers on Nested Table Columns of Views
Можно создать триггер для вложенной в представлении таблицы. В таком триггере также присутствует дополнительная псевдозапись – parent, которая ссылается на всю запись представления (стандартные псевдозаписи old и new ссылаются только на записи вложенной таблицы)
Пример такого триггера
Запускает триггер оператор insert
INSERT INTO TABLE ( SELECT d.emplist FROM dept_view d WHERE department_id = 10 ) VALUES (1001, ‘Glenn’, ‘AC_MGR’, 10000);
Составные DML триггера (compound DML triggers)
Появившиеся в версии 11G эти триггера включают в одном блоке обработку всех видов DML триггеров.
Конструкция compound_dml_trigger:
Где, compound_trigger_block:
timing_point_section:
timing_point:
tps_body:
- Срабатывают такие триггера при разных событиях и в разные моменты времени (на уровне оператора или строки, при вставке/обновлении/удалении, до или после события).
- Не могут быть автономными транзакциями.
- Собирать в коллекцию строки для вставки в другую таблицу, чтобы периодически вставлять их пачкой
- Избежать ошибки мутирующей таблицы (mutating-table error)
Структура составного триггера
- Before statement
- After statement
- Before each row
- After each row
- Нельзя обращаться к псевдозаписям old, new или parent в секциях уровня выражения (before statement и after statement)
- Изменять значения полей псевдозаписи new можно только в секции before each row
- Исключения, сгенерированные в одной секции, нельзя обрабатывать в другой секции
- Если используется оператор goto, он должен указывать на код в той же секции
Пример
create or replace trigger tr_table_test_compound for update or delete or insert on table_test compound trigger v_count pls_integer := 0; before statement is begin dbms_output.put_line ( ‘before statement’ ); end before statement; before each row is begin dbms_output.put_line ( ‘before insert’ ); end before each row; after each row is begin dbms_output.put_line ( ‘after insert’ ); v_count := v_count + 1; end after each row; after statement is begin dbms_output.put_line ( ‘after statement’ ); end after statement; end tr_table_test_compound;
Основные правила определения DML триггеров
- Update of – позволяет указать список изменяемых полей для запуска триггера
- Все условия в заголовке и When … проверяются без запуска триггера на стадии выполнения SQL
- В операторе When можно использовать только встроенные функции
- Можно делать несколько триггеров одного вида, порядок выполнения не определен по умолчанию, но его можно задать с помощью конструкции FOLLOWS TRIGGER_FIRST
- Ограничения уникальности проверяются при изменении записи, то есть после выполнения триггеров before
- Секция объявления переменных определяется словом DECLARE
- Основной блок триггера подчиняется тем же правилам, что и обычные PL/SQL блоки
Ограничения DML триггеров
- нельзя выполнять DDL statements (только в автономной транзакции)
- нельзя запускать подпрограммы с операторами контроля транзакций
- не имеет доступа к SERIALLY_REUSABLE пакетов
- размер не может превышать 32К
- нельзя декларировать переменные типа LONG и LONG RAW
Ошибка мутирования таблицы ORA-04091
- использовать триггеры уровня операции
- автономная транзакция в триггере
- использовать сторонние структуры (коллекции уровня пакета)
- использовать COMPOUND TRIGGER
- изменение самого алгоритма с выносом функционала из триггера
Системные триггеры (System triggers)
Конструкция system_trigger:
Такие триггеры относятся или к схеме, или ко всей базе данных.
- До того, как будет выполнена операция (на которую срабатывает триггер)
- После того, как будет выполнена операция (на которую срабатывает триггер)
- Вместо выполнения оператора Create
Триггеры уровня схемы (schema triggers)
- Срабатывает всегда, когда пользователь-владелец схемы запускает событие (выполняет операцию), на которую должен срабатывать триггер.
- В случае, если любой другой пользователь запускает процедуру/функцию, которая вызывается с правами создателя, и в этой процедуре/функции выполняется операция, на которую создан системный триггер – этот триггер сработает.
Пример триггера
CREATE OR REPLACE TRIGGER drop_trigger BEFORE DROP ON hr.SCHEMA BEGIN RAISE_APPLICATION_ERROR ( num => -20000, msg => ‘Cannot drop object’); END;
Триггеры уровня базы данных (database triggers)
- Такой триггер срабатывает когда любой пользователь БД выполняет команду, на которую создан триггер.
Пример триггера
CREATE OR REPLACE TRIGGER check_user AFTER LOGON ON DATABASE BEGIN check_user; EXCEPTION WHEN OTHERS THEN RAISE_APPLICATION_ERROR (-20000, ‘Unexpected error: ‘|| DBMS_Utility.Format_Error_Stack); END;
Instead of create triggers
- Это триггер уровня схемы, который срабатывает на команду create и заменяет собой эту команду (т.е. вместо выполнения команды create выполняется тело триггера).
Пример триггера
CREATE OR REPLACE TRIGGER t INSTEAD OF CREATE ON SCHEMA BEGIN EXECUTE IMMEDIATE ‘CREATE TABLE T (n NUMBER, m NUMBER)’; END;
Атрибуты системных триггеров
IF (ora_sysevent = ‘LOGON’) THEN v_addr := ora_client_ip_address; END IF;
v_db_name := ora_database_name;
IF (ora_dict_obj_type = ‘USER’) THEN INSERT INTO event_table VALUES (ora_des_encrypted_password); END IF;
INSERT INTO event_table VALUES (‘Changed object is ‘ || ora_dict_obj_name);
IF (ora_sysevent=’ASSOCIATE STATISTICS’) THEN number_modified := ora_dict_obj_name_list(name_list); END IF;
INSERT INTO event_table VALUES (‘object owner is’ || ora_dict_obj_owner);
IF (ora_sysevent=’ASSOCIATE STATISTICS’) THEN number_modified := ora_dict_obj_name_list(owner_list); END IF;
INSERT INTO event_table VALUES (‘This object is a ‘ || ora_dict_obj_type);
IF (ora_sysevent = ‘GRANT’) THEN number_of_grantees := ora_grantee(user_list); END IF;
IF (ora_instance_num = 1) THEN INSERT INTO event_table VALUES (‘1’); END IF;
IF (ora_sysevent = ‘ALTER’ AND ora_dict_obj_type = ‘TABLE’) THEN alter_column := ora_is_alter_column(‘C’); END IF;
IF (ora_sysevent = ‘CREATE’ AND ora_dict_obj_type = ‘TABLE’ AND ora_is_creating_nested_table) THEN INSERT INTO event_table VALUES (‘A nested table is created’); END IF;
IF (ora_sysevent = ‘ALTER’ AND ora_dict_obj_type = ‘TABLE’) THEN drop_column := ora_is_drop_column(‘C’); END IF;
IF ora_is_servererror(error_number) THEN INSERT INTO event_table VALUES (‘Server error!!’); END IF;
SELECT ora_login_user FROM DUAL;
— Retrieve ora_sql_txt into sql_text variable v_n := ora_partition_pos; v_new_stmt := SUBSTR(sql_text,1,v_n — 1) || ‘ ‘ || my_partition_clause || ‘ ‘ || SUBSTR(sql_text, v_n));
IF (ora_sysevent = ‘GRANT’ OR ora_sysevent = ‘REVOKE’) THEN number_of_privileges := ora_privilege_list(privilege_list); END IF;
IF (ora_sysevent = ‘REVOKE’) THEN number_of_users := ora_revokee(user_list); END IF;
INSERT INTO event_table VALUES (‘top stack error ‘ || ora_server_error(1));
n := ora_server_error_depth; — Use n with functions such as ora_server_error
INSERT INTO event_table VALUES (‘top stack error message’ || ora_server_error_msg(1));
n := ora_server_error_num_params(1);
— Second %s in «Expected %s, found %s»: param := ora_server_error_param(1,2);
CREATE TABLE event_table (col VARCHAR2(2030)); DECLARE sql_text ora_name_list_t; n PLS_INTEGER; v_stmt VARCHAR2(2000); BEGIN n := ora_sql_txt(sql_text); FOR i IN 1..n LOOP v_stmt := v_stmt || sql_text(i); END LOOP; INSERT INTO event_table VALUES (‘text of triggering statement: ‘ || v_stmt); END;
INSERT INTO event_table VALUES (ora_sysevent);
IF (ora_sysevent = ‘GRANT’ AND ora_with_grant_option = TRUE) THEN INSERT INTO event_table VALUES (‘with grant option’); END IF;
IF (ora_space_error_info ( eno,typ,owner,ts,obj,subobj) = TRUE) THEN DBMS_OUTPUT.PUT_LINE(‘The object ‘|| obj || ‘ owned by ‘ || owner || ‘ has run out of space.’); END IF;
События срабатывания системных триггеров
Компиляция триггеров
- Триггер создан в состоянии disabled (или переведен в такое состояние)
- Событие триггера after startup on database
- Событие триггера after logon on database или after logon on schema и происходит попытка залогиниться под пользователем System
Исключения в триггерах
- Если событие триггера after startup on database или before shutdown on database
- Если событие триггера after logon on database и пользователь имеет привилегию administer database trigger
- Если событие триггера after logon on schema и пользователь или является владельцем схемы, или имеет привилегию alter any trigger
Порядок выполнения триггеров
Конструкция trigger_ordering_clause:
- Сначала выполняются все before statement триггера
- Потом все before each row триггера
- После все after each row триггера
- И в конце все after statement триггера
Включение/отключение триггеров
Это может понадобиться, например, для загрузки большого объема информации в таблицу.
Выполнить включение/отключение триггера можно с помощью команды:
ALTER TRIGGER [schema.]trigger_name < ENABLE | DISABLE >;
Чтобы включить/отключить сразу все триггеры на таблице:
ALTER TABLE table_name < ENABLE | DISABLE >ALL TRIGGERS;
Для изменения триггера можно или воспользоваться командой Create or replace trigger, или сначала удалить триггер drop trigger, а потом создать заново create trigger.
Операция alter trigger позволяет только включить/отключить триггер, скомпилировать его или переименовать.
Компиляция триггера:
alter trigger TRIGGER_NAME compile;
Права для операций с триггерами
Для работы с триггерами даже в своей схеме необходима привилегия create trigger, она дает права на создание, изменение и удаление.
grant create trigger to USER;
Для работы с триггерами во всех других схемах необходима привилегия * any trigger. Обратите внимание, что права даются отдельно на создание, изменение и удаление.
grant create any trigger to USER; grant alter any trigger to USER; grant drop any trigger to USER;
Для работы с системными триггерами уровня DATABASE необходима привилегия ADMINISTER DATABASE TRIGGER.
grant ADMINISTER DATABASE TRIGGER to USER;
Словари данных с информацией о триггерах:
- dba_triggers – информация о триггерах
- dba_source — код тела триггера
- dba_objects – валидность триггера
Видео-запись лекции, по материалам которой и была написана эта статья:
Множество других видео по темам Oracle можно найти на этом канале: www.youtube.com/c/MoscowDevelopmentTeam
Другие статьи по Oracle
Источник: habr.com