Oracle Database provides three types of database triggers:
1. **Row triggers**: These are fired for each row affected by a DML statement (INSERT, UPDATE or DELETE). Row triggers are useful for enforcing complex business rules, data validation and referential integrity constraints.
2. **Statement triggers**: These are fired once for each DML statement. Statement triggers are useful for auditing changes to tables, generating summary reports and logging events.
3. **System Event triggers**: These are fired based on specific system events such as database startup, shutdown or instance startup. System event triggers are useful for managing the environment, automating administrative tasks and handling exceptional conditions.
Here are some examples of each type of trigger:
1. **Row Trigger Example**: Suppose we have a requirement to enforce a business rule that prevents an employee from earning more than their manager. We can implement this using a row trigger on the EMPLOYEES table as follows:
CREATE OR REPLACE TRIGGER CHECK_EMPLOYEE_SALARY
BEFORE INSERT OR UPDATE ON EMPLOYEES
FOR EACH ROW
DECLARE
manager_salary NUMBER;
BEGIN
SELECT SALARY INTO manager_salary
FROM EMPLOYEES
WHERE EMPLOYEE_ID = :NEW.MANAGER_ID;
IF :NEW.SALARY > manager_salary THEN
RAISE_APPLICATION_ERROR(-20201, 'Employee salary cannot be greater than their manager');
END IF;
END;
This trigger fires before a new row is inserted or an existing row is updated in the EMPLOYEES table, and checks if the salary of the employee is greater than the salary of their manager. If it is, an error is raised and the transaction is rolled back.
2. **Statement Trigger Example**: Suppose we have a requirement to log all changes made to the EMPLOYEES table. We can implement this using a statement trigger as follows:
CREATE OR REPLACE TRIGGER LOG_EMPLOYEE_CHANGES
AFTER INSERT OR UPDATE OR DELETE ON EMPLOYEES
DECLARE
operation VARCHAR2(10);
timestamp TIMESTAMP;
BEGIN
timestamp := SYSTIMESTAMP;
IF INSERTING THEN
operation := 'INSERT';
ELSIF UPDATING THEN
operation := 'UPDATE';
ELSIF DELETING THEN
operation := 'DELETE';
END IF;
INSERT INTO EMPLOYEE_AUDIT (EMPLOYEE_ID, OPERATION, TIME_STAMP)
VALUES (:OLD.EMPLOYEE_ID, operation, timestamp);
END;
This trigger fires after an insert, update or delete statement is executed on the EMPLOYEES table, and logs the operation, employee ID and timestamp to an AUDIT table.
3. **System Event Trigger Example**: Suppose we have a requirement to startup a background job whenever the database is started. We can implement this using a system event trigger as follows:
CREATE OR REPLACE TRIGGER START_BACKGROUND_JOB
AFTER STARTUP ON DATABASE
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'BG_JOB',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN MY_PACKAGE.RUN_BACKGROUND_PROCESS; END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=DAILY; INTERVAL=1',
enabled => TRUE
);
END;
This trigger fires automatically whenever the database is started, and starts a background job using the DBMS_SCHEDULER package. The background job runs a PL/SQL block that executes a package procedure called MY_PACKAGE.RUN_BACKGROUND_PROCESS, once a day.