2012-11-22 25 views
4

这个触发器会将插入的值传递给一个过程,该过程会将这些值插入到另一个表中。我得到一个变异表错误。我怎样才能解决这个问题?我该如何解决这个过程中的突变表触发器

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; 
/
+2

顺便说一句,你的UPDATE语句将在您的发票更新表中的每一行。 – DCookie

+1

我想你想要一个INSERT语句,而不是一个UPDATE。 –

回答

8

该问题是由在触发器本身内引用带有触发器的表引起的。通过更改过程以接受TRT_NO作为参数,不需要在查询中包含APPOINTMENT,这样可以避免变异表异常。根据每次治疗的记录数量,您甚至可以将光标合并到UPDATE语句中。

我认为这应该做到这一点,虽然我一直无法检查数据库。

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; 
/

修订程序:

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; 
/
+4

我已经自由地将UPDATE更正为INSERT,因为UPDATE没有意义。 –

+0

非常感谢您的帮助 – Shimmerstrike