首页 文章

在Oracle中触发更新,改变错误

提问于
浏览
2

我有一个名为Favorites的简单表 .

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表处于变异状态 . 第6行出错 .

我怎么能阻止这个?我搜索了,似乎我的更新将改变我的选择的 Value ,但我不知道如何 .

我使用的是Oracle 11g版 .

2 回答

  • 3

    出现错误消息,因为您的触发器在表内容发生更改时同时查询 Favorite 表( 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. :请参阅上面的更新和测试版本 .

  • 0

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

相关问题