【问题标题】:trigger created but when executed showing some errors==> ORA-04091:, ORA-06512:, ORA-04088:触发器创建但执行时显示一些错误==> ORA-04091:, ORA-06512:, ORA-04088:
【发布时间】:2022-01-20 11:04:09
【问题描述】:

我有一个名为 movie_cast 的表。

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.

此表已经有重复值(#114)。 act_id, mov_id 是外键。我在 movie_cast 表上创建了一个触发器,名为 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')

我的任务是:我想允许此表中的条目,即;一个演员可以做不止一部电影(act_id 可以重复/重复),但我不能为同一部电影两次演员。 有人可以在这里帮助我吗? 从过去的两天开始,我已经厌倦了这个问题! 谢谢!

【问题讨论】:

  • 已经有tons of questions regarding the "is mutating" error。但是你为什么不只使用一个唯一的约束呢?而且你为什么想要这个限制呢?演员可能在一部电影中扮演多个角色,至少在“现实世界”中是这样。
  • 您不能像这样使用触发器来检查其父表。对于这种事情,请尝试查看表约束。
  • 我这样做是因为我想引发自定义错误(您可以在触发器语句第 12 行看到这一点)。我的任务是为此构建触发器或存储过程。这就是我不使用 UNIQUE 约束的原因。
  • 你能帮忙吗?!

标签: sql oracle plsql triggers


【解决方案1】:

您收到ORA-040 mutating 错误,因为您的触发器引用了它触发的表。在 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

【讨论】:

  • 如果答案解决了您的问题,请接受它/这有助于未来有相同或类似问题的提问者,并将问题从未回答队列中删除。请不要将成功回答的问题留作未回答。
  • 好的!怎么做。对不起!但我是 stackoverflow 的新手。
  • here
【解决方案2】:

正如评论者所说,触发器不是防止重复的正确工具。您需要对多个列使用唯一约束。

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

这将允许重复的 MOV_ID 和 ACT_ID,但不允许重复的 MOV_ID + ACT_ID 组合。

【讨论】:

  • 我这样做是因为我想引发自定义错误(您可以在触发器语句第 12 行看到这一点)。我的任务是为此构建触发器或存储过程。这就是我不使用 UNIQUE 约束的原因。
  • 你能帮忙吗?!
  • 您可以使用存储过程执行此操作 - 只需使用相同的逻辑,如果查询符合您的条件,则不要插入。
猜你喜欢
  • 2015-08-06
  • 2013-11-29
  • 1970-01-01
  • 1970-01-01
  • 2019-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多