插入后触发,插入记录时出现错误表突变

时间:2013-07-18 12:24:47

标签: sql oracle triggers relational-database sqlplus

我创建了一个触发器,当新记录插入表Payment时,它将更新Enrollment表(对于账单)。我的触发器如下:

CREATE OR REPLACE TRIGGER EnrollFee_trig
AFTER INSERT ON Enrollment
FOR EACH ROW

DECLARE
amount Payment.TotalPrice%TYPE;
id Payment.LearnerID%TYPE;

BEGIN
SELECT SUM(Price) into amount
FROM LearnerEnrollCourse_View
WHERE LearnerID = :NEW.LearnerID
AND Paid = 'N';

SELECT LearnerID into id
FROM Payment
WHERE LearnerID = :NEW.LearnerID
AND PaymentDate IS NULL;

IF SQL%FOUND THEN
UPDATE Payment 
SET TotalPrice = amount 
WHERE LearnerID = :new.LearnerID
    AND PaymentDate IS NULL;
ELSE  
INSERT INTO Payment VALUES
     (PaymentID_Seq.nextval, :new.LearnerID, '', amount);  
END IF;

END;
/

可以成功创建触发器。但是当将新记录插入Enrollment表时,会出现错误,即“表ENROLLMENT正在变异,触发/功能可能看不到它”。我想更具体地了解造成这个问题的原因以及如何解决它。

1 个答案:

答案 0 :(得分:2)

当我们尝试从行级触发器代码中引用查询中的触发表时,会发生变异表异常。查看更多here

在这种情况下,我怀疑(虽然我不知道LearnerEnrollCourse_View没有定义)问题是由这句话造成的: -

SELECT SUM(Price) into amount
FROM LearnerEnrollCourse_View
WHERE LearnerID = :NEW.LearnerID
AND Paid = 'N';

如果LearnerEnrollCourse_view视图引用了Enrollment表,您将收到变异表错误。有很多方法围绕它,将触发器代码移动到语句级触发器中并将数据保存在包变量中是一种解决方法,但总的来说,我认为使用触发器不是最好的方法,触发你的次数越多有,你越有可能遇到这个问题和其他问题。相反,我会为注册表提供一个api包,并将触发器代码移到那里。

对触发器here

的良好讨论