Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
Home -> Community -> Mailing Lists -> Oracle-L -> Re: mutating table
--0-327254586-970082610=:11462
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Oracle does not allow you to perform DML statements on the target source table in a row level trigger. You can either use a temp table to get modified data from or write a package you''ll find in attachement.
Content-Type: text/plain; name="Just_an_example.txt" Content-Description: Just_an_example.txt Content-Disposition: inline; filename="Just_an_example.txt" /* ** ** ** Background and underlying assumptions: ** ** 1. Table 'po_header' contains Purchase Order (PO) header records. ** Each record is identified by the column 'po_no' (Purchase Order Number), ** the type of Purchase Order is indicated by a column 'po_type', ** and a 'po_status' column indicates the status of the Purchase Order. ** ** 2. Some special processing is required after a particular type of ** Purchase Order is approved, and someone has decided to implement that ** using database triggers rather than by some means which might be more ** sensible - such as via a stored procedure. The special processing causes ** a mutating table error if performed in the row-level trigger. ** ** 3. The package PO_PKG contains procedures for operating on Purchase Orders, ** and a private PL/SQL table which is used by the row-level database trigger to ** register POs for attention by the statement-level trigger.**
-- Create or Replace Package PO_PKG is -- -- Package Specification (incomplete) -- PO_STATUS_APPROVED constant po_header.po_status%type = 'APPROVED'; PO_TYPE_PREVENTIVE_MAINTENANCE constant po_header.po_type%type = 'PM'; -- type po_rectype is record (Pono_f po_header.po_no%type); -- type PONO_Table_type is table of po_rectype index by binary_integer; -- --... -- Among other things which are missing from this package spec are -- the declarations of the procedures! --... end PO_PKG; / Create or replace Package body PO_PKG is -- -- Package Body (incomplete) -- -- PRIVATE PACKAGE VARIABLES -- -- Table of Registered PM PONOs for use by database triggers. -- PMPOT PONO_Table_Type; PMPOT_index binary_integer := 0; -- /* ********************************************************** * PROCEDURE: * Register_Approved_PO * * PURPOSE: * Add the PO number of an Approved Purchase * Order to a package PL/SQL table, for processing by * a statement-level database trigger. * This proc is called by the row-level trigger to record * approved POs which require further processing * which cannot be done at the row-level, due to the 'mutating * table' restriction. * * ARGUMENTS: * Pono_in Purchase Order number * * LIMITATIONS: * Only for use by database triggers. ********************************************************** */ procedure Register_Approved_PO (Pono_in IN VARCHAR2) is begin -- PMPOT_index := PMPOT_index + 1; PMPOT(PMPOT_index).Pono_f := Pono_in ; -- end Register_Approved_PO; /* ********************************************************** * PROCEDURE: * Fixup_Registered_POs * * PURPOSE: * Call procedure 'Fixup_PO' for * all PO's listed in table PMPOT. * This provides additional processing following approval * of a Preventive Maintenance Purchase Order. * * ARGUMENTS: * nil * LIMITATIONS: * Intended for use only by database triggers. ********************************************************** */ procedure Fixup_Registered_Approved_POs is i binary_integer := 0; tmp_pono po_header.po_no%type := null; begin -- for i in 1..PMPOT_index loop tmp_pono := PMPOT(i).Pono_f; Fixup_Approved_PO(tmp_pono); end loop; -- PMPOT.DELETE; PMPOT_index := 0; -- end Fixup_Registered_Approved_POs; /* ********************************************************** * PROCEDURE: * Fixup_Approved_PO * * PURPOSE: * Do whatever is needed for a single purchase order. This * code is not affected by the 'mutating table' problem. * * ARGUMENTS: * pono_in PO Number * * LIMITATIONS: * Only for use by database triggers. ********************************************************** */ procedure Fixup_Approved_PO (pono_in IN VARCHAR2) is begin -- -- Do whatever is needed... -- end Fixup_Approved_PO; --... --... end PO_PKG; / create or replace trigger po_post_update_row after update of po_status on po_header for each row begin /* ** If the PO type is 'Preventive Maintenance' and is approved, ** register it for extra processing at statement level. */ if (:new.po_type = PO_PKG.PO_TYPE_PREVENTIVE_MAINTENANCE) then if :new.po_status = PO_PKG.PO_STATUS_APPROVED then PO_PKG.Register_Approved_PO(:new.po_no); end if; end if; end; / create or replace trigger po_post_update_stmtReceived on Wed Sep 27 2000 - 14:23:30 CDT