Oracle中的触发器更新,变异错误

Oracle中的触发器更新,变异错误,oracle,plsql,Oracle,Plsql,我有一张简单的表格叫做收藏夹 Favorites | username | type_of_movie | like_or_dislike | 数据如下所示: AAA, Action, Like AAA, Romance, Dislike ... 我已经做了一个触发器来计算最喜欢的类型,并防止用户喜欢所有类型 CREATE OR REPLACE TRIGGER trgLike BEFORE INSERT OR UPDATE ON Favorite FOR EACH ROW DECLARE

我有一张简单的表格叫做收藏夹

Favorites
| username | type_of_movie | like_or_dislike |
数据如下所示:

AAA, Action, Like
AAA, Romance, Dislike
...
我已经做了一个触发器来计算最喜欢的类型,并防止用户喜欢所有类型

CREATE OR REPLACE TRIGGER trgLike
BEFORE INSERT OR UPDATE ON Favorite
FOR EACH ROW
DECLARE
    count number;
BEGIN
 SELECT
 COUNT(username) INTO count
 FROM
 Favorite
 WHERE
 username= :NEW.username AND like_or_dislike = 'Like';
 IF (count = 3) THEN
    RAISE_APPLICATION_ERROR(-20000,'Too much liking');
 END IF;    
END;
/
我希望用户能够喜欢3种类型的电影

insert触发器工作得很好,但当我尝试更新不喜欢的内容时,我得到了错误ORA-04091,表发生了变化。第6行出错

我怎样才能防止这种情况?我已经搜索过了,我的更新似乎会改变我选择的值,但我不知道如何改变


我正在使用Oracle版本11g。

出现错误消息,因为触发器在更改表内容的同时查询
收藏的
表(更新
插入

为了解决此问题,您需要三个触发器和一个小程序包:

CREATE OR REPLACE PACKAGE state_pkg AS
    type ridArray IS TABLE OF rowid INDEX BY binary_integer;
    newRows ridArray;
    empty ridArray;
END;
/

CREATE OR REPLACE TRIGGER trgLike_clear_table 
    BEFORE INSERT OR UPDATE ON Favorite 
BEGIN 
    state_pkg.newRows := state_pkg.empty;
END;
/

CREATE OR REPLACE TRIGGER trgLike_capture_affected_rows 
    AFTER INSERT OR UPDATE ON Favorite FOR EACH ROW 
BEGIN 
    state_pkg.newRows(state_pkg.newRows.count +1) := :new.rowid;
END;
/

CREATE OR REPLACE TRIGGER trgLike_do_work 
    AFTER INSERT OR UPDATE ON Favorite 
DECLARE    
    likes NUMBER;
BEGIN 
  FOR i IN 1..state_pkg.newRows.count LOOP
    SELECT COUNT(*) INTO likes
      FROM Favorite
    WHERE username = (SELECT username FROM Favorite WHERE rowid = state_pkg.newRows(i))
      AND like_or_dislike = 'Like';
      IF (likes = 3) THEN
          RAISE_APPLICATION_ERROR(-20000, 'Too much liking');
      END IF;
    END LOOP;
END;
/ 
在AskTom有一个关于这一点的讨论


p.s.:请参阅上面的更新和测试版本。

您可以在触发器中使用物化视图。

谢谢!我现在明白了。同时,我认识的人建议我使用pragma autonomy_事务;自治事务提供了一种非常有趣和强大的方法,我经常在日志或审计的上下文中使用它们。但是,我不确定它们是否是您的推荐产品。例如,请检查此帖子中的答案:。最终取决于特定的任务;但总的来说,我同意贾斯汀的观点。再加上这个++的一百万美元,我们已经在这些令人讨厌的突变触发问题上浪费了很多时间,因为我们的数据库是多年来创建的,没有设计好,没有礼貌地说些别的话。这很有效。