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