Compound Trigger
ORA-04091: Mutating, Trigger Error in Oracle with Example
Topic Introduction: In this tutorial, we will discuss the mutating table error in Oracle and fix it using a compound trigger.
When a table is mutating, it is changing. If the change is taking place and we try to make another change in the middle of the first change, Oracle will issue a mutating table error with the error code ORA-04091.
Specifically, the error results from the following operations:
- We update data to a table.
- A row-level trigger associated with the table automatically fires and makes another change to the table.
EMPLOYEE_ID
FIRST_NAME
LAST_NAME
PHONE_NUMBER
HIRE_DATE
JOB_ID
SALARY
COMMISSION_PCT
MANAGER_ID
DEPARTMENT_ID
Here we want to update the salary for an employee. But the company has a binding that we can give a salary greater than 5 times of lowest salary, and the system automatically assigns 5 times of lowest salary to the employee if we want to update a salary greater than 5 times of lowest salary.
CREATE OR REPLACE TRIGGER EMPLOYEES_SAL_POLICYAFTER INSERT OR UPDATEON EMPLOYEESFOR EACH ROWDECLAREL_MAX_SAL EMPLOYEES.SALARY%TYPE;BEGIN-- get the lowest salary without zeroSELECT MIN (SALARY) * 5INTO L_MAX_SALFROM EMPLOYEESWHERE SALARY > 0;-- check with the new salaryIF L_MAX_SAL < :NEW.SALARYTHENUPDATE EMPLOYEESSET SALARY = L_MAX_SALWHERE EMPLOYEE_ID = :NEW.EMPLOYEE_ID;END IF;END;/
This statement the credit limit of the customer 1 to 12000:
Update Statement for increase salary of EMPLOYEE_ID 200 where Present salary is 4400 to 20100. In this table, the lowest salary is 2100
UPDATE EMPLOYEESSET EMPLOYEES = 20100WHERE EMPLOYEE_ID = 200;
The update action fires the trigger and Oracle issues the following mutating table error: ORA-04091: table OT.CUSTOMERS are mutating, trigger/function may not see it
The update statement changes the data of the
Employees table. The trigger fires and attempts to make another change
while the first change is in the progress, which results in an error.
Fixing The Mutating Table Error:
CREATE OR REPLACE TRIGGER EMPLOYEES_SAL_POLICYFOR UPDATE OR INSERT ON EMPLOYEESCOMPOUND TRIGGERTYPE R_EMPLOYEES_TYPE IS RECORD (EMPLOYEE_ID EMPLOYEES.EMPLOYEE_ID%TYPE,SALARY EMPLOYEES.SALARY%TYPE);TYPE T_EMPLOYEES_TYPE IS TABLE OF R_EMPLOYEES_TYPEINDEX BY PLS_INTEGER;T_EMPLOYEE T_EMPLOYEES_TYPE;AFTER EACH ROW ISBEGINT_EMPLOYEE (T_EMPLOYEE.COUNT + 1).EMPLOYEE_ID :=:NEW.EMPLOYEE_ID;T_EMPLOYEE (T_EMPLOYEE.COUNT).SALARY := :NEW.SALARY;END AFTER EACH ROW;AFTER STATEMENT ISL_MAX_SAL EMPLOYEES.SALARY%TYPE;BEGINSELECT MIN (SALARY) * 5INTO L_MAX_SALFROM EMPLOYEESWHERE SALARY > 0;FOR INDX IN 1 .. T_EMPLOYEE.COUNTLOOPIF L_MAX_SAL < T_EMPLOYEE (INDX).SALARYTHENUPDATE EMPLOYEESSET SALARY = L_MAX_SALWHERE EMPLOYEE_ID = T_EMPLOYEE (INDX).EMPLOYEE_ID;END IF;END LOOP;END AFTER STATEMENT;END;
Trigger Effects:
- Declare an array of customer records that includes customer id and credit limit.
- Collect affected rows into the array in the row-level trigger.
- Update each affected row in the statement level trigger.
Note 1. Use this compound trigger code if the database 11g and later.
No comments