在 Oracle 中触发更新,发生变异错误

Trigger update in Oracle, mutating error

我有一个简单的 table 收藏夹。

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 种类型的电影。

插入触发器运行良好,但当我尝试更新不喜欢的内容时,出现错误 ORA-04091 table 正在突变。第 6 行出错。

我该如何防止这种情况发生?我已经搜索过,似乎我的更新会改变我的 select 的值,但我不知道如何改变。

我使用的是 Oracle 版本 11g。

出现错误消息,因为您的触发器同时查询 Favorite table 而 table 内容正在更改(UPDATEINSERT).

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

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 上有关于此的 nice article

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

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