触发器创建但执行时显示一些错误==> ORA-04091:, ORA-06512:, ORA-04088:

trigger created but when executed showing some errors==> ORA-04091:, ORA-06512:, ORA-04088:

我有一个名为 movie_cast 的 table。

SQL> select * from  movie_cast;

    ACT_ID     MOV_ID ROLE
---------- ---------- --------------------------------------------------
       101        901 John Scottie Ferguson
       102        902 Miss Giddens
       103        903 T. E. Lawrence
       104        904 Michael
       105        905 Antonio Salieri
       106        906 Rick Deckard
       107        907 Alice Harford
       108        908 McManus
       109        909 J. J. Gittes
       110        910 Eddie Adams
       111        911 Alvy Singer
       112        912 San
       113        913 Adny Dufresne
       114        914 Lester Burnham
       115        915 Rose DeWitt Bukater
       116        916 Sean Maguire
       117        917 Ed
       118        918 Renton
       119        919 Alfred Borden
       120        920 Elizabeth Darko
       121        921 Older Jamal
       122        922 Ripley
       114        923 Bobby Darin

23 rows selected.

这个table已经有重复值(#114)。 act_id, mov_id 是外键。我在 movie_cast table 上创建了一个名为 trg1.

的触发器
SQL> CREATE OR REPLACE TRIGGER trg1
  2  after INSERT ON MOVIE_CAST
  3  FOR EACH ROW
  4  DECLARE
  5  num NUMBER;
  6  BEGIN
  7  SELECT COUNT(act_ID)
  8  INTO num
  9  FROM movie_cast
 10  WHERE mov_ID=:NEW.mov_ID;
 11  if(num >= 1) then
 12  dbms_output.put_line('Already cast assigned,same Actors cant cast more than once');
 13  end if;
 14  END;
 15  /

Trigger created.

虽然创建了触发器,但执行后出现一些错误

(SQL> insert into movie_cast values(124, 921, 'abc');
insert into movie_cast values(124, 921, 'abc')
            *
ERROR at line 1:
ORA-04091: table PROJECT_MOVIE_DATA.MOVIE_CAST is mutating, trigger/function may not see it
ORA-06512: at "PROJECT_MOVIE_DATA.TRG1", line 4
ORA-04088: error during execution of trigger 'PROJECT_MOVIE_DATA.TRG1')

我的任务是:我想允许在此 table 中输入,即;一个演员可以拍不止一部电影(act_id 可以是 repetitive/duplicate),但我不能为同一部电影选派同一个演员两次。 有人可以帮我吗? 我受够了过去两天的这个问题! 谢谢!

正如评论者所提到的,触发器不是防止重复的正确工具。您想要多列的唯一约束。

ALTER TABLE movie_cast ADD CONSTRAINT uk_movie_cast_actor UNIQUE (mov_id, act_id);

这将允许重复 MOV_ID 和 ACT_IDs,但不允许 MOV_ID + ACT_ID.

的重复组合

您收到 ORA-040 mutating 错误,因为您的触发器引用了它触发的 table。在 Oracle 中,您基本上不能这样做。处理此问题的正确方法是创建唯一常量,然后在异常发生时拦截并处理异常,无论是在 plsql 过程中还是在应用程序错误处理中。参见 demo

create or replace 
procedure generate_actor_movie_role( 
          actor_id_in movie_cast.act_id%type
        , movie_id_in movie_cast.mov_id%type
        , role_in     movie_cast.role%type
        ) 
is 
begin 
    insert into movie_cast (act_id, mov_id, role)  
         values ( actor_id_in, movie_id_in, role_in); 
exception 
    when dup_val_on_index then
         begin 
             log_error( 'generate_actor_movie_role'
                       , dbms_utility.format_error_stack
                       ); 
             raise_application_error ( -20001, 'Already cast assigned,same Actors cant cast more than once');
         end ; 
end generate_actor_movie_role; 

注意:使用 dbms_output 实际上是没有用的,至少在生产环境中是这样,因为它从未见过。它实际上也将异常转换为自定义错误,但仍然作为异常。该演示还包含极简错误记录程序。
请注意@stickybit 的提交,因为演员在给定的电影中扮演多个角色。也许你的约束应该包括 role.