Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6065339
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 23, 20262026-05-23T09:22:45+00:00 2026-05-23T09:22:45+00:00

In our database we have a table, in which records are referenced by id

  • 0

In our database we have a table, in which records are referenced by id from about 4 other tables. These ‘child’ tables have a foreign key to the ‘master’ table, with ‘on delete set null’. All tables have a mutating-tables system (ie: package with plsql-table, process the records when procedure gets called from after statement trigger).
However, upon deletion of a record in the master-table, the child-record gives the ‘table is mutating’-error. Which i find kind of odd, since the foreign-key seems to trigger some implicit update-statement, which lands in the plsql-table.

All i’m after is trying to find why this is, i can’t seem to dredge up some relevant info!
Sure, we do have a solution to this by simply setting the referenced id field to null in the associated tables, from the after-statement trigger of the master, but i’d still like to know why this happens.

Code to reproduce the error:

CREATE TABLE master_table (ID NUMBER(5) NOT NULL);
CREATE TABLE child_table (ID NUMBER(5) NOT NULL, master_id NUMBER(5));

alter table master_table add constraint master_pk primary key (ID);

alter table child_table add constraint child_pk primary key (ID);

ALTER TABLE child_table
  add constraint on_delete_master foreign key (master_id)
  references master_table (ID) on delete set null;

CREATE OR REPLACE PACKAGE pkg_child
IS
PROCEDURE init_temp;
PROCEDURE add_temp(i_action IN VARCHAR2, 
                   i_master_old IN child_table.master_id%TYPE, 
                   i_master_new IN child_table.master_id%TYPE);
PROCEDURE process_temp;
END;
/
CREATE OR REPLACE PACKAGE BODY pkg_child IS
   TYPE temp_record IS RECORD(
      action        VARCHAR2(1),
      old_master_id child_table.master_id%TYPE,
      new_master_id child_table.master_id%TYPE);

   TYPE type_temp IS TABLE OF temp_record INDEX BY BINARY_INTEGER;

   tab_temp type_temp;

   PROCEDURE init_temp IS
   BEGIN
      tab_temp.delete;
   END;

   PROCEDURE add_temp(i_action     IN VARCHAR2,
                      i_master_old IN child_table.master_id%TYPE,
                      i_master_new IN child_table.master_id%TYPE) IS
      v_id BINARY_INTEGER;
   BEGIN
      v_id := nvl(tab_temp.last, 0) + 1;
      tab_temp(v_id).action := i_action;
      tab_temp(v_id).old_master_id := i_master_old;
      tab_temp(v_id).new_master_id := i_master_new;
   END;

   PROCEDURE process_temp IS
      v_id    BINARY_INTEGER;
      v_total NUMBER;
   BEGIN
      v_id := tab_temp.first;
      WHILE v_id IS NOT NULL LOOP
         IF tab_temp(v_id).action = 'U' THEN
            SELECT COUNT(1)
              INTO v_total
              FROM child_table;
         END IF;
         v_id := tab_temp.next(v_id);
      END LOOP;
   END;
END;
/
CREATE OR REPLACE TRIGGER child_table_bs
 BEFORE 
 INSERT OR UPDATE OR DELETE
 ON child_table
 REFERENCING OLD AS OLD NEW AS NEW
BEGIN
  pkg_child.init_temp;
END;
/
CREATE OR REPLACE TRIGGER child_table_ar
 AFTER 
 INSERT OR DELETE OR UPDATE
 ON child_table
 REFERENCING OLD AS OLD NEW AS NEW
 FOR EACH ROW 
DECLARE
   v_action VARCHAR2(1);
BEGIN
   IF inserting THEN
      v_action := 'I';
   ELSIF updating THEN
      v_action := 'U';
   ELSIF deleting THEN
      v_action := 'D';
   END IF;
   pkg_child.add_temp(v_action, :old.id, :new.id);
END;
/
CREATE OR REPLACE TRIGGER child_table_as
 AFTER 
 INSERT OR UPDATE OR DELETE
 ON child_table
 REFERENCING OLD AS OLD NEW AS NEW
BEGIN
 pkg_child.process_temp;
END;
/

INSERT ALL 
   INTO master_table (id) VALUES (1) 
   INTO master_table (id) VALUES (2) 
   INTO master_table (id) VALUES (3) 
   INTO master_table (id) VALUES (4)
SELECT * FROM dual;

INSERT ALL
   INTO child_table (id, master_id) VALUES (1, NULL) 
   INTO child_table (id, master_id) VALUES (2, 1) 
   INTO child_table (id, master_id) VALUES (3, 2) 
   INTO child_table (id, master_id) VALUES (4, NULL)
SELECT * FROM dual;

-- error on this delete: mutating tables
-- why?
DELETE FROM master_table
 WHERE id = 2;

Clean-up Code:

DROP TRIGGER child_table_bs;
DROP TRIGGER child_table_ar;
DROP TRIGGER child_table_as;
DROP PACKAGE pkg_child;
DROP TABLE child_table;
DROP TABLE master_table;

Thanks

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-23T09:22:46+00:00Added an answer on May 23, 2026 at 9:22 am

    You have one statement, the DELETE from the master table which can affect multiple rows.
    Because of the CASCADE constraint, each deleted row will fire off an implicit/recursive UPDATE statement of the CHILD table. That is, you can in theory have multiple UPDATEs of the child table.

    Say you did a DELETE FROM master_table WHERE id in (1, 2)

    That would generate two UPDATE child_table statements. Each of those would try to execute the AFTER UPDATE trigger so you’d get two executions of

    SELECT COUNT(1)
    INTO v_total
    FROM child_table
    

    The results of any SELECT under the single DELETE statement should be consistent at a particular point in time. But the SELECT isn’t occurring at the end of the DELETE, but is executed multiple times during the delete, each time potentially with a different result. Oracle can work out which result you want/expect, so throws the mutating table error.

    Without knowing the business requirements, it is hard to recommend a solution. Like Oracle, we don’t know what you are trying to do. Possibly the situation can be resolved by an ON-COMMIT MV or a DBMS_JOB that will execute at the end of the transaction.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

We've encountered the following situation in our database. We have table 'A' and table
Our application has a table which stores all transactions records of clients in one
Which one is faster to have database key as String or as Long? If
I have a database which has an orders table and inventory table. The order-items
i have two tables which form part of my login/register system: these are userlogin
I have a database which has a table with an XML column. The XML
We have a table in our system that would benefit from a numeric column
I have a parent/child relationship defined which, unfortunately, cannot be maintained via a foreign
In our database, we have the following tables Tags Id (int) Name (string) IsActive
Our database server is a SQL 2008 server. My colleagues all have XP service

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.