Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i fix this Mutating table from a procedure an trigger

This trigger will pass on inserted values to a procedure which will insert those values in another table. I'm getting a mutating table error. How can i fix this?

CREATE OR REPLACE TRIGGER ADD_INVOICE
BEFORE INSERT OR UPDATE OF APP_NO,C_NO ON APPOINTMENT
FOR EACH ROW
DECLARE
BEGIN

POP_INVOICE(:NEW.APP_NO,:NEW.C_NO,:NEW.APP_DATE);

END;
/

CREATE OR REPLACE PROCEDURE POP_INVOICE(
I_APP_NO IN INVOICE.APP_NO%TYPE,
I_C_NO IN INVOICE.C_NO%TYPE,
I_INV_DATE IN INVOICE.INV_DATE%TYPE)
AS
CURSOR C_POP IS SELECT PRICE FROM TREATMENT T,APPOINTMENT A 
WHERE T.TRT_NO=A.TRT_NO
AND A.APP_NO=I_APP_NO;

V_BILL INVOICE.BILL%TYPE;
BEGIN

OPEN C_POP; 
FETCH C_POP INTO V_BILL;

UPDATE INVOICE
SET INV_NO=INV_IDSEQ.NEXTVAL,
APP_NO=I_APP_NO,
C_NO=I_C_NO,
BILL=V_BILL,
INV_DATE=I_INV_DATE;

END;
/
like image 285
Shimmerstrike Avatar asked Nov 22 '12 19:11

Shimmerstrike


People also ask

How do you fix a mutating trigger error?

If a trigger does result in a mutating table error, the only real option is to rewrite the trigger as a statement-level trigger. Mutating table errors only impact row level triggers. But to use a statement level trigger, some data may need to be preserved from each row, to be used by the statement level trigger.

What is a mutating table error and how can you get around it?

When something mutates, it is changing. Something that is changing is hard to analyze and to quantify. A mutating table error (ORA-04091) occurs when a row-level trigger tries to examine or change a table that is already undergoing change (via an INSERT, UPDATE, or DELETE statement).

Which of the following triggers Cannot modify a mutating table?

Create Statement Level Trigger instead of Row Level Trigger. Row Level Triggers can't read Mutating tables- Change Row Level Trigger to Statement Level Trigger. IF we omit the 'For Each Row' clause from above Trigger, it will become statement level Trigger.

What is mutating in trigger?

if the trigger attempts to select or modify the table while the trigger has not completed (ie. table is in transition). then mutating trigger error occurs. because the table is in middle of a transaction so it causes the trigger to mutate. you can change the trigger to statement level and apply the logic there.


1 Answers

The problem is caused by referencing the table with the trigger on it within the trigger itself. Changing the procedure to accept the TRT_NO as a parameter removes the need to include APPOINTMENT in the query, and so will avoid the mutating table exception. Depending on how many records there are for each treatment, you could even incorporate the cursor into your UPDATE statement.

I think this should do it, although I haven't been able to check against a database.

CREATE OR REPLACE TRIGGER ADD_INVOICE

BEFORE INSERT OR UPDATE OF APP_NO,C_NO ON APPOINTMENT
FOR EACH ROW
DECLARE
BEGIN

POP_INVOICE(:NEW.APP_NO,:NEW.C_NO,:NEW.APP_DATE,:NEW.TRT_NO);

END;
/

The revised procedure:

CREATE OR REPLACE PROCEDURE POP_INVOICE(
I_APP_NO IN INVOICE.APP_NO%TYPE,
I_C_NO IN INVOICE.C_NO%TYPE,
I_INV_DATE IN INVOICE.INV_DATE%TYPE,
I_TRT_NO IN APPOINTMENT.TRT_NO%TYPE
)
AS

CURSOR C_POP IS SELECT PRICE 
FROM TREATMENT T
WHERE T.TRT_NO = I_TRT_NO;

V_BILL INVOICE.BILL%TYPE;

BEGIN

OPEN C_POP; 
FETCH C_POP INTO V_BILL;
CLOSE C_POP;

INSERT INVOICE
  (inv_no, app_no, c_no, bill, inv_date)
VALUES
  (INV_IDSEQ.NEXTVAL, I_APP_NO, I_C_NO, V_BILL, I_INV_DATE);


END;
/
like image 50
steve godfrey Avatar answered Oct 13 '22 19:10

steve godfrey