9.9 Trigger Design Guidelines
- 
                     Use triggers to ensure that whenever a specific event occurs, any necessary actions are done (regardless of which user or application issues the triggering statement). For example, use a trigger to ensure that whenever anyone updates a table, its log file is updated. 
- 
                     Do not create triggers that duplicate database features. For example, do not create a trigger to reject invalid data if you can do the same with constraints (see "How Triggers and Constraints Differ"). 
- 
                     Do not create triggers that depend on the order in which a SQL statement processes rows (which can vary). For example, do not assign a value to a global package variable in a row trigger if the current value of the variable depends on the row being processed by the row trigger. If a trigger updates global package variables, initialize those variables in a BEFOREstatement trigger.
- 
                     Use BEFORErow triggers to modify the row before writing the row data to disk.
- 
                     Use AFTERrow triggers to obtain the row ID and use it in operations.An AFTERrow trigger fires when the triggering statement results in ORA-02292.Note: AFTERrow triggers are slightly more efficient thanBEFORErow triggers. WithBEFORErow triggers, affected data blocks are read first for the trigger and then for the triggering statement. WithAFTERrow triggers, affected data blocks are read only for the trigger.
- 
                     
                     If the triggering statement of a BEFORErow trigger is anUPDATEorDELETEstatement that conflicts with anUPDATEstatement that is running, then the database does a transparentROLLBACKtoSAVEPOINTand restarts the triggering statement. The database can do this many times before the triggering statement completes successfully. Each time the database restarts the triggering statement, the trigger fires. TheROLLBACKtoSAVEPOINTdoes not undo changes to package variables that the trigger references. To ensure that there are no unwanted side effects with each restart, make sure that theBEFORErow trigger is idempotent, meaning the trigger should be written so that the result remains the same with each subsequent execution. Any additional work that should not be repeated can be handled in anAFTERrow trigger. To detect this situation, you can also include a counter variable in the package.
- 
                     Do not create recursive triggers. For example, do not create an AFTERUPDATEtrigger that issues anUPDATEstatement on the table on which the trigger is defined. The trigger fires recursively until it runs out of memory.
- 
                     If you create a trigger that includes a statement that accesses a remote database, then put the exception handler for that statement in a stored subprogram and invoke the subprogram from the trigger. For more information, see "Remote Exception Handling". 
- 
                     Use DATABASEtriggers judiciously. They fire every time any database user initiates a triggering event.
- 
                     If a trigger runs the following statement, the statement returns the owner of the trigger, not the user who is updating the table: SELECT Username FROM USER_USERS; 
- 
                     Only committed triggers fire. A trigger is committed, implicitly, after the CREATETRIGGERstatement that creates it succeeds. Therefore, the following statement cannot fire the trigger that it creates:CREATE OR REPLACE TRIGGER my_trigger AFTER CREATE ON DATABASE BEGIN NULL; END; / 
- 
                     To allow the modular installation of applications that have triggers on the same tables, create multiple triggers of the same type, rather than a single trigger that runs a sequence of operations. Each trigger sees the changes made by the previously fired triggers. Each trigger can see OLDandNEWvalues.