Создание события

Функция

Определение оператора объявления нового события.

Спецификация
   
< создание события >::=
CREATE [IF NOT EXISTS | OR REPLACE] [GLOBAL] [PRIVATE]
EVENT [имя схемы.]имя события [AUTORESET] [WITHOUT SOURCE]
[AS { запрос выборки | [TRANSACTION]
{DELETE | UPDATE | INSERT} [, ...] ON [имя схемы.]имя таблицы}
| TIME {CURRENT |(символьное выражение[, символьный формат])}
[CYCLE количество единиц {SECOND | MINUTE | HOUR | DAY}]}]
[EXECUTE имя хранимой процедуры (список параметров) [AS CURRENT_USER]] [DISABLE]
Синтаксические правила
  1. < Имя события > должно иметь уникальное в БД имя среди имен событий в пределах < имя схемы >.

  2. < Имя таблицы > должно ссылаться на базовую таблицу.

  3. Если < имя схемы > не указано, то подразумевается схема пользователя, который подает запрос.

  4. Опция OR REPLACE заставляет удалять существующее в БД событие и создавать его под тем же именем, но с другими параметрами.

  5. Опция IF NOT EXISTS отменяет выполнение оператора, если указанное событие уже существует в БД.

  6. Одновременное использование опций IF NOT EXISTS и OR REPLACE запрещено.

  7. Если задан модификатор GLOBAL, будет создано хранимое событие, запоминаемое в системной таблице $$$EVENTS. По умолчанию создается несохраняемое событие (т.е. событие будет известно только в текущем сеансе работы СУБД ЛИНТЕР).

  8. Созданное несохраняемое событие существует до тех пор, пока не будет уничтожено командой DROP EVENT или не произойдет завершение работы ядра СУБД ЛИНТЕР.

  9. Если задан модификатор PRIVATE, то создается личное событие, владельцем которого является создавший его пользователь БД. Для доступа к такому событию другие пользователи БД должны указывать полное имя события в виде «< имя схемы >.< имя события >». Если этот модификатор не задан, к событию другого пользователя можно обращаться просто по имени события. В ситуации, когда пользователь имеет доступ к событию другого пользователя с тем же именем, что и его личное событие, при указании только имени события (без уточнения его владельца) операция будет проведена над личным событием пользователя.

  10. < Запрос выборки > определяет запрос, который должен автоматически выполняться при реальном изменении любой из таблиц, участвующих в этом запросе. СУБД ЛИНТЕР будет устанавливать данное событие, если < запрос выборки > вернул непустое множество ответов.

    create event "Select_All_From_Auto_Person" as select * from auto, person where auto.personid=person.personid;
    create event MOD_AUTO as delete, update on auto;
  11. Для создания события необходимы права чтения на все используемые таблицы (уровень прав CONNECT).

  12. Если событие относится к объекту, хранящемуся в удаленном узле распределенной БД, то данное событие будет видно только в программе, создавшей это событие. На удаленном узле оно будет неизвестно.

  13. Событие, созданное с модификатором AUTORESET, автоматически сбрасывается (удаляется) из очереди событий после рассылки оповещения (уведомления) о наступлении события всем пользователям, ожидающим этого события. Например, если пользователь создал событие с модификатором AUTORESET и затем оповестил о его наступлении с помощью команды SET EVENT, то оно будет сброшено после рассылки СУБД уведомления о наступлении события всем пользователя, ожидающим этого события по команде WAIT EVENT.

  14. Модификатор AUTORESET можно задавать для всех типов событий, кроме SELECT.

  15. Модификатор WITHOUT SOURCE действует только на хранимые события, сохраняемые в системной таблице $$$EVENTS, т.е. имеющие модификатор GLOBAL. Для всех остальных событий он игнорируется. Он запрещает сохранение текста запроса на создание события в системной таблице $$$EVENTS, вследствие чего отключенное событие не может быть включено вновь командой «ALTER EVENT … ENABLE;».

  16. Если перед опциями INSERT, UPDATE или DELETE стоит модификатор TRANSACTION, это означает, что событие будет наступать не в момент подачи запросов INSERT, UPDATE или DELETE, а в момент подачи COMMIT для транзакции, включающей соответствующие запросы.

  17. Модификатор TIME заставляет генерировать событие в определённое время (событие по таймеру). Если в качестве времени указан модификатор CURRENT, то событие наступит сразу после его создания по данной команде.

  18. < Символьное выражение > и < символьный формат > задают время генерации события по таймеру. Синтаксис этих параметров аналогичен параметрам функции TO_DATE (см. пункт «Преобразование символьного представления типа «дата-время» во внутреннее»). Если в качестве времени наступления события указано прошедшее время, событие наступит сразу же после создания.

  19. Модификатор CYCLE задает создание повторяющегося события, т.е. события, которое будет постоянно генерироваться через определённый промежуток времени после своего первого наступления. Частота генерации события задается с помощью двух параметров:

    • < количество единиц > – количество единиц времени (значение от 1 до 65535);

    • {SECOND | MINUTE | HOUR | DAY} – величина единицы времени.

  20. Модификатор CYCLE можно указать только в случае наличия модификатора AUTORESET.

  21. Модификатор AUTORESET для событий по таймеру можно указать только при наличии модификатора CYCLE.

  22. Модификатор EXECUTE заставляет выполнять при наступлении создаваемого события указанную хранимую процедуру с конкретными аргументами. Для события на SELECT-запрос модификатор EXECUTE выполняет процедуру в том случае, если при проверке события оно установлено (SELECT-запрос вернул непустую выборку), а при предыдущей проверке оно не было установлено (SELECT-запрос вернул пустую выборку) или текущая проверка – первая сразу после создания события. Если при последовательных проверках события SELECT-запрос каждый раз возвращает непустую выборку, то повторные вызовы процедуры производиться не будут.

  23. Если задан модификатор AS CURRENT_USER, то процедура будет выполнена от имени того пользователя, действия которого вызвали наступление события, в противном случае процедура будет выполнена от имени пользователя, создавшего событие.

  24. Модификатор AS CURRENT_USER нельзя задавать для событий по таймеру.

  25. На время выполнения процедуры, активизируемой при наступлении события, генерирование порождающих её вызов событий не блокируется, поэтому вполне возможна ситуация, когда событие наступает часто, а процедура не успевает выполниться в промежуток между двумя наступившими событиями. В этом случае игнорируются все необработанные процедурой события, кроме последнего. Например, если за время выполнения процедуры, активизированной по наступлению события, было сгенерировано 100 таких же событий, то данная процедура будет вызвана еще только один раз (даже после прекращения генерации вызывающих её активизацию событий).

  26. Если задан модификатор DISABLE, событие сразу же после создания будет отключено. Этот модификатор можно задать только для хранимых событий, создаваемых с модификатором GLOBAL. Отключённое событие можно либо удалить, либо включить с помощью команды «ALTER EVENT … ENABLE;».

Пример

Для выполнения примера в БД должна быть создана системная таблица $$$EVENTS. Приведённые ниже запросы выполняются утилитой inl (см. документ «СУБД ЛИНТЕР. Командный интерфейс», раздел «Обработка SQL-операторов»).

  1. Создаём таблицу для протоколирования событий и процедуру, которая будет выполнять протоколирование событий с периодичностью 5 секунд:

    create or replace table test_proc_table(i int, dt date);
    create or replace procedure test_proc(in i int) result int
    code
      print(dtoa(sysdate(), "DD.MM.YYYY HH24:MI.SS.FF") + ", "+ username() + ", " + itoa(i+10)); //
      execute direct "insert into test_proc_table (i,dt) values ("+itoa(i+10)+",sysdate);"; //
      sleep(5000); //
    end;
  2. Создаём отключённое событие по таймеру с цикличностью 1 сек.:

    create or replace global event "TIME_EVENT" autoreset as time ('14.04.08 13:15', 'DD.MM.YY HH:MI') cycle 1 second execute test_proc(1000) disable;
  3. Включаем событие:

    alter event "TIME_EVENT" enable;
  4. Наблюдаем на консоли СУБД ЛИНТЕР распечатку информации из периодически запускаемой процедуры. Также можно выполнить запрос:

    select * from test_proc_table;

    Получим ответ в виде:

     I           DT
     -           --
    |       1010|16.05.2008:13:10:23.00|
    |       1010|16.05.2008:13:10:28.00|
    |       1010|16.05.2008:13:10:33.00|
    |       1010|16.05.2008:13:10:38.00|
    …
  5. Убеждаемся, что процедура запускается через 5 секунд, хотя при создании события мы указали «cycle 1». Событие наступает действительно через каждую секунду, однако, поскольку процедура не закончила свою работу через 1 секунду, она в этот момент не запускается. Чтобы убедиться в том, что приведённое объяснение правильно, меняем в запросе на создание события строку «cycle 1» на «cycle 7» и заново повторяем пункты 2 – 4. Убеждаемся, что процедура запускается через каждые 7 секунд, как и должно быть:

     I           DT
     -           --
    |       1010|16.05.2008:13:10:23.00|
    |       1010|16.05.2008:13:10:28.00|
    |       1010|16.05.2008:13:10:33.00|
    |       1010|16.05.2008:13:10:38.00|
    |       1010|16.05.2008:13:10:40.00|
    |       1010|16.05.2008:13:10:47.00|

    (жирным шрифтом выделены новые строки).

  6. Удаляем событие:

    drop event "TIME_EVENT";