Note:
This topic applies only to simple triggers.
Database event publication lets applications subscribe to database events, just like they subscribe to messages from other applications. The database events publication framework includes the following features:
By creating a trigger, you can specify a subprogram that runs when an event occurs. DML events are supported on tables, and database events are supported on DATABASE and SCHEMA. You can turn notification on and off by enabling and disabling the trigger using the ALTER TRIGGER statement.
This feature is integrated with the Advanced Queueing engine. Publish/subscribe applications use the DBMS_AQ.ENQUEUE procedure, and other applications such as cartridges use callouts.
When the database detects an event, the trigger mechanism executes the action specified in the trigger. The action can include publishing the event to a queue so that subscribers receive notifications. To publish events, use the DBMS_AQ package.
Note:
The database can detect only system-defined events. You cannot define your own events.
When it detects an event, the database fires all triggers that are enabled on that event, except the following:
For example, a trigger for all DROP events does not fire when it is dropped itself.
For example, recursive DDL within a system trigger might modify a trigger, which prevents the modified trigger from being fired by events within the same transaction.
When an event is published, certain run-time context and attributes, as specified in the parameter list, are passed to the callout subprogram. A set of functions called event attribute functions are provided.
For each supported database event, you can identify and predefine event-specific attributes for the event. You can choose the parameter list to be any of these attributes, along with other simple expressions. For callouts, these are passed as IN arguments.
Return status from publication callout functions for all events are ignored. For example, with SHUTDOWN events, the database cannot do anything with the return status.
Traditionally, triggers execute as the definer of the trigger. The trigger action of an event is executed as the definer of the action (as the definer of the package or function in callouts, or as owner of the trigger in queues). Because the owner of the trigger must have EXECUTE privileges on the underlying queues, packages, or subprograms, this action is consistent.
When the database fires a trigger, you can retrieve certain attributes about the event that fired the trigger. You can retrieve each attribute with a function call. Table 9-3 describes the system-defined event attributes.
Note:
TYPE ora_name_list_t IS TABLE OF VARCHAR2(64);
| Attribute | Type | Description | Example |
|---|---|---|---|
ora_client_ip_address |
VARCHAR2 |
Returns IP address of the client in a LOGON event when the underlying protocol is TCP/IP |
DECLARE
v_addr VARCHAR2(11);
BEGIN
IF (ora_sysevent = 'LOGON') THEN
v_addr := ora_client_ip_address;
END IF;
END;
|
ora_database_name |
VARCHAR2(50) |
Database name. |
DECLARE v_db_name VARCHAR2(50); BEGIN v_db_name := ora_database_name; END; |
ora_des_encrypted_password |
VARCHAR2 |
The DES-encrypted password of the user being created or altered. |
IF (ora_dict_obj_type = 'USER') THEN
INSERT INTO event_table
VALUES (ora_des_encrypted_password);
END IF;
|
ora_dict_obj_name |
VARCHAR(30) |
Name of the dictionary object on which the DDL operation occurred. |
INSERT INTO event_table
VALUES ('Changed object is ' ||
ora_dict_obj_name);
|
ora_dict_obj_name_list (name_list OUT ora_name_list_t) |
PLS_INTEGER |
Return the list of object names of objects being modified in the event. |
DECLARE
name_list DBMS_STANDARD.ora_name_list_t;
number_modified PLS_INTEGER;
BEGIN
IF (ora_sysevent='ASSOCIATE STATISTICS')
THEN number_modified :=
ora_dict_obj_name_list(name_list);
END IF;
END;
|
ora_dict_obj_ow |
VARCHAR(30) |
Owner of the dictionary object on which the DDL operation occurred. |
INSERT INTO event_table
VALUES ('object owner is' ||
ora_dict_obj_owner);
|
ora_dict_obj_owner_list (owner_list OUT ora_name_list_t) |
PLS_INTEGER |
Returns the list of object owners of objects being modified in the event. |
DECLARE
owner_list
DBMS_STANDARD.ora_name_list_t;
number_modified PLS_INTEGER;
BEGIN
IF (ora_sysevent='ASSOCIATE STATISTICS')
THEN number_modified :=
ora_dict_obj_name_list(owner_list);
END IF;
END;
|
ora_dict_obj_type |
VARCHAR(20) |
Type of the dictionary object on which the DDL operation occurred. |
INSERT INTO event_table
VALUES ('This object is a ' ||
ora_dict_obj_type);
|
ora_grantee (user_list OUT ora_name_list_t) |
PLS_INTEGER |
Returns the grantees of a grant event in the OUT parameter; returns the number of grantees in the return value. |
DECLARE user_list DBMS_STANDARD.ora_name_list_t; number_of_grantees PLS_INTEGER; BEGIN IF (ora_sysevent = 'GRANT') THEN number_of_grantees := ora_grantee(user_list); END IF; END; |
ora_instance_num |
NUMBER |
Instance number. |
IF (ora_instance_num = 1) THEN
INSERT INTO event_table VALUES ('1');
END IF;
|
ora_is_alter_column (column_name IN VARCHAR2) |
BOOLEAN |
Returns true if the specified column is altered. |
IF (ora_sysevent = 'ALTER' AND
ora_dict_obj_type = 'TABLE') THEN
alter_column := ora_is_alter_column('C');
END IF;
|
ora_is_creating_nested_table |
BOOLEAN |
Returns true if the current event is creating a nested table |
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;
|
ora_is_drop_column (column_name IN VARCHAR2) |
BOOLEAN |
Returns true if the specified column is dropped. |
IF (ora_sysevent = 'ALTER' AND
ora_dict_obj_type = 'TABLE') THEN
drop_column := ora_is_drop_column('C');
END IF;
|
ora_is_servererror |
BOOLEAN |
Returns TRUE if given error is on error stack, FALSE otherwise. |
IF ora_is_servererror(error_number) THEN
INSERT INTO event_table
VALUES ('Server error!!');
END IF;
|
ora_login_user |
VARCHAR2(30) |
Login user name. |
SELECT ora_login_user FROM DUAL; |
ora_partition_pos |
PLS_INTEGER |
In an INSTEAD OF trigger for CREATE TABLE, the position within the SQL text where you can insert a PARTITION clause. |
-- Retrieve ora_sql_txt into
-- sql_text variable first.
v_n := ora_partition_pos;
v_new_stmt := SUBSTR(sql_text,1,v_n - 1)
|| ' ' || my_partition_clause
|| ' ' || SUBSTR(sql_text, v_n));
|
ora_privilege_list (privilege_list OUT ora_name_list_t) |
PLS_INTEGER |
Returns the list of privileges being granted by the grantee or the list of privileges revoked from the revokees in the OUT parameter; returns the number of privileges in the return value. |
DECLARE
privelege_list
DBMS_STANDARD.ora_name_list_t;
number_of_privileges PLS_INTEGER;
BEGIN
IF (ora_sysevent = 'GRANT' OR
ora_sysevent = 'REVOKE') THEN
number_of_privileges :=
ora_privilege_list(privilege_list);
END IF;
END;
|
ora_revokee (user_list OUT ora_name_list_t) |
PLS_INTEGER |
Returns the revokees of a revoke event in the |
DECLARE user_list DBMS_STANDARD.ora_name_list_t; number_of_users PLS_INTEGER; BEGIN IF (ora_sysevent = 'REVOKE') THEN number_of_users := ora_revokee(user_list); END IF; END; |
ora_server_error |
NUMBER |
Given a position (1 for top of stack), it returns the error number at that position on error stack |
INSERT INTO event_table
VALUES ('top stack error ' ||
ora_server_error(1));
|
ora_server_error_depth |
PLS_INTEGER |
Returns the total number of error messages on the error stack. |
n := ora_server_error_depth; -- This value is used with other functions -- such as ora_server_error |
ora_server_error_msg (position in pls_integer) |
VARCHAR2 |
Given a position (1 for top of stack), it returns the error message at that position on error stack |
INSERT INTO event_table
VALUES ('top stack error message' ||
ora_server_error_msg(1));
|
ora_server_error_num_params (position in pls_integer) |
PLS_INTEGER |
Given a position (1 for top of stack), it returns the number of strings that were substituted into the error message using a format like %s. |
n := ora_server_error_num_params(1); |
ora_server_error_param (position in pls_integer, param in pls_integer) |
VARCHAR2 |
Given a position (1 for top of stack) and a parameter number, returns the matching substitution value (%s, %d, and so on) in the error message. |
-- For example, the second %s in a -- message: "Expected %s, found %s" param := ora_server_error_param(1,2); |
ora_sql_txt (sql_text out ora_name_list_t) |
PLS_INTEGER |
Returns the SQL text of the triggering statement in the OUT parameter. If the statement is long, it is broken into multiple PL/SQL table elements. The function return value shows the number of elements are in the PL/SQL table. |
--...
-- Create table event_table
create table event_table (col
VARCHAR2(2030));
--...
DECLARE
sql_text DBMS_STANDARD.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;
|
ora_sysevent |
VARCHAR2(20) |
Database event firing the trigger: Event name is same as that in the syntax. |
INSERT INTO event_table VALUES (ora_sysevent); |
ora_with_grant_option |
BOOLEAN |
Returns true if the privileges are granted with grant option. |
IF (ora_sysevent = 'GRANT' and
ora_with_grant_option = TRUE) THEN
INSERT INTO event_table
VALUES ('with grant option');
END IF;
|
space_error_info (error_number OUT NUMBER, error_type OUT VARCHAR2, object_owner OUT VARCHAR2, table_space_name OUT VARCHAR2, object_name OUT VARCHAR2, sub_object_name OUT VARCHAR2) |
BOOLEAN |
Returns true if the error is related to an out-of-space condition, and fills in the OUT parameters with information about the object that caused the error. |
IF (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;
|
Database events are related to entire instances or schemas, not individual tables or rows. Triggers associated with startup and shutdown events must be defined on the database instance. Triggers associated with on-error and suspend events can be defined on either the database instance or a particular schema.
| Event | When Trigger Fires | Conditions | Restrictions | Transaction | Attribute Functions |
|---|---|---|---|---|---|
STARTUP |
When the database is opened. |
None allowed |
No database operations allowed in the trigger. Return status ignored. |
Starts a separate transaction and commits it after firing the triggers. |
ora_sysevent ora_login_user ora_instance_num ora_database_name |
SHUTDOWN |
Just before the server starts the shutdown of an instance. This lets the cartridge shutdown completely. For abnormal instance shutdown, this triiger might not fire. |
None allowed |
No database operations allowed in the trigger. Return status ignored. |
Starts a separate transaction and commits it after firing the triggers. |
ora_sysevent ora_login_user ora_instance_num ora_database_name |
DB_ROLE_CHANGE |
When the database is opened for the first time after a role change. |
None allowed |
Return status ignored. |
Starts a separate transaction and commits it after firing the triggers. |
ora_sysevent ora_login_user ora_instance_num ora_database_name |
SERVERERROR |
When the error eno occurs. If no condition is given, then this trigger fires whenever an error occurs. The trigger does not fire on ORA-1034, ORA-1403, ORA-1422, ORA-1423, and ORA-4030 because they are not true errors or are too serious to continue processing. It also fails to fire on ORA-18 and ORA-20 because a process is not available to connect to the database to record the error. |
ERRNO = eno |
Depends on the error. Return status ignored. |
Starts a separate transaction and commits it after firing the triggers. |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_server_error ora_is_servererror space_error_info |
Client events are the events related to user logon/logoff, DML, and DDL operations.
The LOGON and LOGOFF events allow simple conditions on UID and USER. All other events allow simple conditions on the type and name of the object, as well as functions like UID and USER.
The LOGON event starts a separate transaction and commits it after firing the triggers. All other events fire the triggers in the existing user transaction.
The LOGON and LOGOFF events can operate on any objects. For all other events, the corresponding trigger cannot perform any DDL operations, such as DROP and ALTER, on the object that caused the event to be generated.
The DDL allowed inside these triggers is altering, creating, or dropping a table, creating a trigger, and compile operations.
If an event trigger becomes the target of a DDL operation (such as CREATE TRIGGER), it cannot fire later during the same transaction
| Event | When Trigger Fires | Attribute Functions |
|---|---|---|
BEFORE ALTER AFTER ALTER |
When a catalog object is altered. |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_dict_obj_type ora_dict_obj_name ora_dict_obj_owner ora_des_encrypted_password (for ALTER USER events) ora_is_alter_column (for ALTER TABLE events) ora_is_drop_column (for ALTER TABLE events) |
BEFORE DROP AFTER DROP |
When a catalog object is dropped. |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_dict_obj_type ora_dict_obj_name ora_dict_obj_owner |
BEFORE ANALYZE AFTER ANALYZE |
When an analyze statement is issued |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_dict_obj_name ora_dict_obj_type ora_dict_obj_owner |
BEFORE ASSOCIATE STATISTICS AFTER ASSOCIATE STATISTICS |
When an associate statistics statement is issued |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_dict_obj_name ora_dict_obj_type ora_dict_obj_owner ora_dict_obj_name_list ora_dict_obj_owner_list |
BEFORE AUDIT AFTER AUDIT BEFORE NOAUDIT AFTER NOAUDIT |
When an audit or noaudit statement is issued |
ora_sysevent ora_login_user ora_instance_num ora_database_name |
BEFORE COMMENT AFTER COMMENT |
When an object is commented |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_dict_obj_name ora_dict_obj_type ora_dict_obj_owner |
BEFORE CREATE AFTER CREATE |
When a catalog object is created. |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_dict_obj_type ora_dict_obj_name ora_dict_obj_owner ora_is_creating_nested_table (for CREATE TABLE events) |
BEFORE DDL AFTER DDL |
When most SQL DDL statements are issued. Not fired for ALTER DATABASE,CREATE CONTROLFILE, CREATE DATABASE, and DDL issued through the PL/SQL subprogram interface, such as creating an advanced queue. |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_dict_obj_name ora_dict_obj_type ora_dict_obj_owner |
BEFORE DISASSOCIATE STATISTICS AFTER DISASSOCIATE STATISTICS |
When a disassociate statistics statement is issued |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_dict_obj_name ora_dict_obj_type ora_dict_obj_owner ora_dict_obj_name_list ora_dict_obj_owner_list |
BEFORE GRANT AFTER GRANT |
When a grant statement is issued |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_dict_obj_name ora_dict_obj_type ora_dict_obj_owner ora_grantee ora_with_grant_option ora_privileges |
BEFORE LOGOFF |
At the start of a user logoff |
ora_sysevent ora_login_user ora_instance_num ora_database_name |
AFTER LOGON |
After a successful logon of a user. |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_client_ip_address |
BEFORE RENAME AFTER RENAME |
When a rename statement is issued. |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_dict_obj_name ora_dict_obj_owner ora_dict_obj_type |
BEFORE REVOKE AFTER REVOKE |
When a revoke statement is issued |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_dict_obj_name ora_dict_obj_type ora_dict_obj_owner ora_revokee ora_privileges |
AFTER SUSPEND |
After a SQL statement is suspended because of an out-of-space condition. The trigger must correct the condition so the statement can be resumed. |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_server_error ora_is_servererror space_error_info |
BEFORE TRUNCATE AFTER TRUNCATE |
When an object is truncated |
ora_sysevent ora_login_user ora_instance_num ora_database_name ora_dict_obj_name ora_dict_obj_type ora_dict_obj_owner |