Создание события
Функция
Определение оператора объявления нового события.
Спецификация
::=
EVENT [имя схемы.]имя события [AUTORESET] [WITHOUT SOURCE]
[AS { запрос выборки | [TRANSACTION]
{DELETE | UPDATE | INSERT} [, ...] ON [имя схемы.]имя таблицы}
| TIME {CURRENT |(символьное выражение[, символьный формат])}
[CYCLE количество единиц {SECOND | MINUTE | HOUR | DAY}]}]
[EXECUTE имя хранимой процедуры (список параметров) [AS CURRENT_USER]] [DISABLE]
Синтаксические правила
-
< Имя события >
должно иметь уникальное в БД имя среди имен событий в пределах< имя схемы >
. -
< Имя таблицы >
должно ссылаться на базовую таблицу. -
Если
< имя схемы >
не указано, то подразумевается схема пользователя, который подает запрос. -
Опция
OR REPLACE
заставляет удалять существующее в БД событие и создавать его под тем же именем, но с другими параметрами. -
Опция
IF NOT EXISTS
отменяет выполнение оператора, если указанное событие уже существует в БД. -
Одновременное использование опций
IF NOT EXISTS
иOR REPLACE
запрещено. -
Если задан модификатор
GLOBAL
, будет создано хранимое событие, запоминаемое в системной таблице$$$EVENTS
. По умолчанию создается несохраняемое событие (т.е. событие будет известно только в текущем сеансе работы СУБД ЛИНТЕР). -
Созданное несохраняемое событие существует до тех пор, пока не будет уничтожено командой
DROP EVENT
или не произойдет завершение работы ядра СУБД ЛИНТЕР. -
Если задан модификатор
PRIVATE
, то создается личное событие, владельцем которого является создавший его пользователь БД. Для доступа к такому событию другие пользователи БД должны указывать полное имя события в виде «< имя схемы >.< имя события >
». Если этот модификатор не задан, к событию другого пользователя можно обращаться просто по имени события. В ситуации, когда пользователь имеет доступ к событию другого пользователя с тем же именем, что и его личное событие, при указании только имени события (без уточнения его владельца) операция будет проведена над личным событием пользователя. -
< Запрос выборки >
определяет запрос, который должен автоматически выполняться при реальном изменении любой из таблиц, участвующих в этом запросе. СУБД ЛИНТЕР будет устанавливать данное событие, если< запрос выборки >
вернул непустое множество ответов.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;
-
Для создания события необходимы права чтения на все используемые таблицы (уровень прав
CONNECT
). -
Если событие относится к объекту, хранящемуся в удаленном узле распределенной БД, то данное событие будет видно только в программе, создавшей это событие. На удаленном узле оно будет неизвестно.
-
Событие, созданное с модификатором
AUTORESET
, автоматически сбрасывается (удаляется) из очереди событий после рассылки оповещения (уведомления) о наступлении события всем пользователям, ожидающим этого события. Например, если пользователь создал событие с модификаторомAUTORESET
и затем оповестил о его наступлении с помощью командыSET EVENT
, то оно будет сброшено после рассылки СУБД уведомления о наступлении события всем пользователя, ожидающим этого события по командеWAIT EVENT
. -
Модификатор
AUTORESET
можно задавать для всех типов событий, кромеSELECT
. -
Модификатор
WITHOUT SOURCE
действует только на хранимые события, сохраняемые в системной таблице$$$EVENTS
, т.е. имеющие модификаторGLOBAL
. Для всех остальных событий он игнорируется. Он запрещает сохранение текста запроса на создание события в системной таблице$$$EVENTS
, вследствие чего отключенное событие не может быть включено вновь командой «ALTER EVENT … ENABLE;
». -
Если перед опциями
INSERT
,UPDATE
илиDELETE
стоит модификаторTRANSACTION
, это означает, что событие будет наступать не в момент подачи запросовINSERT
,UPDATE
илиDELETE
, а в момент подачиCOMMIT
для транзакции, включающей соответствующие запросы. -
Модификатор
TIME
заставляет генерировать событие в определённое время (событие по таймеру). Если в качестве времени указан модификаторCURRENT
, то событие наступит сразу после его создания по данной команде. -
< Символьное выражение >
и< символьный формат >
задают время генерации события по таймеру. Синтаксис этих параметров аналогичен параметрам функцииTO_DATE
(см. пункт «Преобразование символьного представления типа «дата-время» во внутреннее»). Если в качестве времени наступления события указано прошедшее время, событие наступит сразу же после создания. -
Модификатор
CYCLE
задает создание повторяющегося события, т.е. события, которое будет постоянно генерироваться через определённый промежуток времени после своего первого наступления. Частота генерации события задается с помощью двух параметров:-
< количество единиц >
– количество единиц времени (значение от 1 до 65535); -
{
SECOND
|MINUTE
|HOUR
|DAY
} – величина единицы времени.
-
-
Модификатор
CYCLE
можно указать только в случае наличия модификатораAUTORESET
. -
Модификатор
AUTORESET
для событий по таймеру можно указать только при наличии модификатораCYCLE
. -
Модификатор
EXECUTE
заставляет выполнять при наступлении создаваемого события указанную хранимую процедуру с конкретными аргументами. Для события на SELECT-запрос модификаторEXECUTE
выполняет процедуру в том случае, если при проверке события оно установлено (SELECT-запрос вернул непустую выборку), а при предыдущей проверке оно не было установлено (SELECT-запрос вернул пустую выборку) или текущая проверка – первая сразу после создания события. Если при последовательных проверках события SELECT-запрос каждый раз возвращает непустую выборку, то повторные вызовы процедуры производиться не будут. -
Если задан модификатор
AS CURRENT_USER
, то процедура будет выполнена от имени того пользователя, действия которого вызвали наступление события, в противном случае процедура будет выполнена от имени пользователя, создавшего событие. -
Модификатор
AS CURRENT_USER
нельзя задавать для событий по таймеру. -
На время выполнения процедуры, активизируемой при наступлении события, генерирование порождающих её вызов событий не блокируется, поэтому вполне возможна ситуация, когда событие наступает часто, а процедура не успевает выполниться в промежуток между двумя наступившими событиями. В этом случае игнорируются все необработанные процедурой события, кроме последнего. Например, если за время выполнения процедуры, активизированной по наступлению события, было сгенерировано 100 таких же событий, то данная процедура будет вызвана еще только один раз (даже после прекращения генерации вызывающих её активизацию событий).
-
Если задан модификатор
DISABLE
, событие сразу же после создания будет отключено. Этот модификатор можно задать только для хранимых событий, создаваемых с модификаторомGLOBAL
. Отключённое событие можно либо удалить, либо включить с помощью команды «ALTER EVENT … ENABLE;
».
Пример
Для выполнения примера в БД должна быть создана системная таблица $$$EVENTS
. Приведённые ниже запросы выполняются утилитой inl
(см. документ «СУБД ЛИНТЕР. Командный интерфейс»,
раздел «Обработка SQL-операторов»).
-
Создаём таблицу для протоколирования событий и процедуру, которая будет выполнять протоколирование событий с периодичностью 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;
-
Создаём отключённое событие по таймеру с цикличностью 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;
-
Включаем событие:
alter event "TIME_EVENT" enable;
-
Наблюдаем на консоли СУБД ЛИНТЕР распечатку информации из периодически запускаемой процедуры. Также можно выполнить запрос:
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 секунд, хотя при создании события мы указали «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| …
(жирным шрифтом выделены новые строки).
-
Удаляем событие:
drop event "TIME_EVENT";