DEV Community

umzzil nng
umzzil nng

Posted on Originally published at oraerror.com

Oracle ORA-04073 Error: Causes and Solutions Complete Guide

ORA-04073: Column List Not Valid for This Trigger Type

ORA-04073 is a compile-time Oracle error that occurs when you specify a column list (OF column_name) in a trigger definition where it is not permitted. The OF clause is exclusively valid for UPDATE triggers in Oracle DML triggers, and using it with INSERT, DELETE, or INSTEAD OF triggers immediately raises this error.


Top 3 Causes

1. Using OF Clause with INSERT or DELETE Triggers

The most common cause is attaching OF column_name to an INSERT or DELETE event. Oracle's syntax strictly reserves the OF clause for UPDATE triggers only.

Incorrect (causes ORA-04073):

CREATE OR REPLACE TRIGGER trg_bad_insert
BEFORE INSERT OF salary ON employees
FOR EACH ROW
BEGIN
  DBMS_OUTPUT.PUT_LINE('Salary: ' || :NEW.salary);
END;
/
Enter fullscreen mode Exit fullscreen mode

Fixed:

CREATE OR REPLACE TRIGGER trg_good_insert
BEFORE INSERT ON employees
FOR EACH ROW
BEGIN
  DBMS_OUTPUT.PUT_LINE('New Salary: ' || :NEW.salary);
END;
/
Enter fullscreen mode Exit fullscreen mode

2. Misplacing OF in Compound Event Triggers

When combining multiple DML events (INSERT, UPDATE, DELETE), developers sometimes incorrectly append the OF clause to the entire event list instead of only to the UPDATE keyword.

Incorrect (causes ORA-04073):

CREATE OR REPLACE TRIGGER trg_bad_compound
BEFORE INSERT OR UPDATE OR DELETE OF salary ON employees
FOR EACH ROW
BEGIN
  NULL;
END;
/
Enter fullscreen mode Exit fullscreen mode

Fixed — use UPDATING('column') inside the body instead:

CREATE OR REPLACE TRIGGER trg_good_compound
BEFORE INSERT OR UPDATE OR DELETE ON employees
FOR EACH ROW
BEGIN
  IF INSERTING THEN
    DBMS_OUTPUT.PUT_LINE('Row inserted.');
  ELSIF UPDATING('SALARY') THEN
    DBMS_OUTPUT.PUT_LINE('Salary changed: ' || :OLD.salary || ' -> ' || :NEW.salary);
  ELSIF DELETING THEN
    DBMS_OUTPUT.PUT_LINE('Row deleted.');
  END IF;
END;
/
Enter fullscreen mode Exit fullscreen mode

3. Using OF Clause in INSTEAD OF Triggers

INSTEAD OF triggers, used on views, do not support the OF column_name clause at all. Any attempt to include it will immediately raise ORA-04073.

Incorrect (causes ORA-04073):

CREATE OR REPLACE TRIGGER trg_bad_instead
INSTEAD OF UPDATE OF salary ON emp_view
FOR EACH ROW
BEGIN
  UPDATE employees SET salary = :NEW.salary
  WHERE employee_id = :OLD.employee_id;
END;
/
Enter fullscreen mode Exit fullscreen mode

Fixed:

CREATE OR REPLACE TRIGGER trg_good_instead
INSTEAD OF UPDATE ON emp_view
FOR EACH ROW
BEGIN
  IF UPDATING('SALARY') THEN
    UPDATE employees
    SET salary = :NEW.salary
    WHERE employee_id = :OLD.employee_id;
  END IF;
END;
/
Enter fullscreen mode Exit fullscreen mode

Quick Fix Summary

Trigger Type OF Clause Allowed? Recommended Alternative
INSERT ❌ No Use :NEW.column in body
DELETE ❌ No Use :OLD.column in body
UPDATE ✅ Yes UPDATE OF col ON table
INSTEAD OF ❌ No Use UPDATING('col') in body
Compound Events ⚠️ UPDATE only Use UPDATING('col') function

Prevention Tips

1. Standardize trigger templates in your team
Always define a standard trigger DDL template that includes a comment noting that OF column_list is only valid for UPDATE triggers. Validate all trigger DDL in a development environment before deploying to production.

2. Prefer UPDATING('column_name') over the OF clause
Make it a team coding standard to use the UPDATING(), INSERTING, and DELETING conditional predicates inside the trigger body rather than relying on the OF clause. This approach works universally across all trigger types and eliminates the risk of ORA-04073 entirely while keeping your trigger logic more readable and maintainable.

-- Preferred pattern: column-level check inside trigger body
CREATE OR REPLACE TRIGGER trg_best_practice
BEFORE UPDATE ON employees
FOR EACH ROW
BEGIN
  IF UPDATING('SALARY') THEN
    -- handle salary change
    :NEW.last_updated := SYSDATE;
  END IF;
END;
/
Enter fullscreen mode Exit fullscreen mode

📖 Want a more detailed guide?
Check out the full in-depth version (Korean) on oraerror.com — includes detailed analysis, additional SQL examples, and prevention tips.

Top comments (0)