6.3 Schema-Level Event TriggersOracle8 i also allows you to define triggers to respond to schema-level events (also known as user-level events), including the following: Good news! We are finally able to place triggers on this broad set of DDL! We can keep track of any attempts to drop tables (successful or otherwise), can notify DBAs of changes to tables or types, and so on. Here is the syntax for these triggers: CREATE [ OR REPLACE ] TRIGGER trigger_name { BEFORE | AFTER } { SERVERERROR | LOGON | LOGOFF | CREATE | DROP | ALTER } ON schema_name .SCHEMA BEGIN pl/sql_statements END;
You must have the CREATE ANY TRIGGER system privilege to create a trigger in any schema, on a table in any schema, or on another user's schema ( schema _ name .SCHEMA in the syntax just given). You will also need privileges to access any of the external references in the trigger's PL/SQL code. You can define triggers for the same event (such as SERVERERROR) on both the schema and database levels. In this case, the schema-level trigger will fire before the database level, but both will fire. Table 6.4 describes the different schema-level events on which you may define a trigger.
Each user event has an associated set of attributes. These attributes are actually functions owned by SYS that return the values of characteristics relevant to the event. The current set of available attributes includes those listed in the previous section on database-level events (see Table 6.2 ), plus those listed in Table 6.5 .
Table 6.6 lists the restrictions and attributes for each schema-level event.
6.3.1 A Schema-Level Event Trigger ExampleSuppose that I want to make sure that even if a user is able to connect to a schema, she or he will not be able to drop tables from that schema. Without these DDL triggers, that would be impossible because, if I can connect, I "own" everything and can do with them what I want. With the DROP trigger, however, I can add this extra level of security. The following trigger asserts the following rule: you cannot drop any tables starting with "EMP" in the SCOTT schema: /* Filename on companion disk: stopdrop.trg */ CREATE OR REPLACE TRIGGER no_drop_trg BEFORE DROP ON SCOTT.SCHEMA DECLARE v_msg VARCHAR2(1000) := 'No drop allowed on ' || DICTIONARY_OBJ_OWNER || '.' || DICTIONARY_OBJ_NAME || ' from ' || LOGIN_USER; BEGIN IF DICTIONARY_OBJ_OWNER = 'SCOTT' AND DICTIONARY_OBJ_NAME LIKE 'EMP%' AND DICTIONARY_OBJ_TYPE = 'TABLE' THEN watch.topipe; watch.action ( 'BEFORE DROP trigger', v_msg); RAISE_APPLICATION_ERROR ( -20905, v_msg); END IF; END; / I rely on the special attributes available to me in this trigger -- namely, the functions returning values for DICTIONARY_OBJ_OWNER, DICTIONARY_OBJ_NAME, and DICTIONARY_OBJ_TABLE, to indicate whether the specified table being dropped is out of bounds. If so, I send a message to my watch pipe and then stop the drop request by raising an exception. Here's what happens when I attempt to drop a now-undroppable table: SQL> drop table emp2; drop table emp2 * ERROR at line 1: ORA-00604: error occurred at recursive SQL level 1 ORA-20905: No drop allowed on SCOTT.EMP2 from SCOTT Copyright (c) 2000 O'Reilly & Associates. All rights reserved. |
|