当前位置: 首页 > 面试题库 >

ORA-04091:表[blah]正在突变,触发器/功能可能看不到它

梅飞龙
2023-03-14
问题内容

我最近开始处理大型复杂的应用程序,由于这个错误,我刚刚被分配了一个错误:

ORA-04091: table SCMA.TBL1 is mutating, trigger/function may not see it
ORA-06512: at "SCMA.TRG_T1_TBL1_COL1", line 4
ORA-04088: error during execution of trigger 'SCMA.TRG_T1_TBL1_COL1'

有问题的触发器看起来像

    create or replace TRIGGER TRG_T1_TBL1_COL1
   BEFORE  INSERT OR UPDATE OF t1_appnt_evnt_id ON TBL1
   FOR EACH ROW
   WHEN (NEW.t1_prnt_t1_pk is not  null)
   DECLARE
        v_reassign_count number(20);
   BEGIN
       select count(t1_pk) INTO v_reassign_count from TBL1
              where  t1_appnt_evnt_id=:new.t1_appnt_evnt_id and t1_prnt_t1_pk is not null;
       IF (v_reassign_count > 0) THEN
           RAISE_APPLICATION_ERROR(-20013, 'Multiple reassignments not allowed');
       END IF;
   END;

该表具有主键“ t1_pk”,“约会事件ID” t1_appnt_evnt_id和另一列“
t1_prnt_t1_pk”,该列可能包含也可能不包含另一行的t1_pk

这似乎触发正试图确保以相同的其他人t1_appnt_evnt_id 提到了同样一个该行指的是 一个转诊到另一行,如果这个人是指到另一行。

DBA对错误报告的评论是“删除触发器,然后执行代码中的检查”,但不幸的是,他们在Hibernate之上有一个专有的代码生成框架,因此我什至无法弄清楚它的实际位置被写出来,所以我希望有一种方法可以使此触发器起作用。在那儿?


问题答案:

我认为我不同意您对触发器要执行的操作的描述。在我看来,它旨在执行此业务规则:对于给定的t1_appnt_event值,一次只有一行可以具有t1_prnt_t1_pk的非NULL值。(它们是否在第二列中具有相同的值都没有关系。)

有趣的是,它是为UPDATE OF t1_appnt_event而不是其他列定义的,因此我认为有人可以通过更新第二列来打破规则,除非该列有单独的触发器。

您可能有一种方法可以创建一个基于函数的索引来强制执行此规则,以便完全摆脱触发器。我想出了一种方法,但是需要一些假设:

  • 该表具有数字主键
  • 主键和t1_prnt_t1_pk始终都是正数

如果这些假设成立,则可以创建如下函数:

dev> create or replace function f( a number, b number ) return number deterministic as
  2  begin
  3    if a is null then return 0-b; else return a; end if;
  4  end;

和这样的索引:

CREATE UNIQUE INDEX my_index ON my_table
  ( t1_appnt_event, f( t1_prnt_t1_pk, primary_key_column) );

因此,PMNT列为NULL的行将出现在索引中,并且主键的倒数为第二个值,因此它们永远不会相互冲突。不为NULL的行将使用列的实际(正)值。违反约束的唯一方法是,如果两行中的两行都具有相同的非NULL值。

这可能是“聪明”的做法,但它可能会帮助您解决问题。

Paul Tomblin的更新:我继续更新了igor在评论中提出的原始想法:

 CREATE UNIQUE INDEX cappec_ccip_uniq_idx 
 ON tbl1 (t1_appnt_event, 
    CASE WHEN t1_prnt_t1_pk IS NOT NULL THEN 1 ELSE t1_pk END);


 类似资料:
  • 问题内容: 我做了这个触发器,在将行插入表TEST_TRNCOMPVISIT时,出现以下错误- 发生以下错误: ORA-04091:表TEST.TEST_TRNCOMPVISIT正在变异,触发器/函数可能看不到它 ORA-06512:在“ TEST.UPDATE_TEST_280510”,第4行 ORA-06512:在“ TEST.UPDATE_TEST_280510”,第10行 ORA-0408

  • 本文向大家介绍Oracle触发器表发生了变化 触发器不能读它的解决方法(必看),包括了Oracle触发器表发生了变化 触发器不能读它的解决方法(必看)的使用技巧和注意事项,需要的朋友参考一下 出现原因,是因为在更新的的表和读取的表是同一个表。 出现错误时,是因为触发器在T_userupdateT在T_user上,触发器内部有读取了T_user所以有错误。 修改如下 多了PRAGMA AUTONOM

  • 我想用quartz scheduler使用jdbc数据存储立即执行作业~。然而,即使我使用now()或调用triggerjob进行调度,在调度和触发器fire之间也有20-30秒的延迟。 我尝试用一个简单的触发器执行作业: 并且我还尝试用调度程序触发: 下面是显示延迟的侦听器日志。

  • 我正在尝试向使用Apollo的GraphQL服务器发送突变查询。 然而,我只看到实现这一点的唯一方法是使用突变组件。https://www.apollographql.com/docs/react/essentials/mutations/#the-突变成分 有没有一种简单的方法可以发送这样的突变? 从“graphql标记”导入gql;

  • 我在Azure上有一个函数,包含以下function.json文件: 除非我错了,否则这个函数应该每天运行一次,在凌晨3点? 这是函数的签名: 我到底做错了什么?当我手动触发(在门户中单击“运行”)时,该功能工作正常,但它在今天凌晨3点没有运行,昨天也没有运行。 编辑:所以,正如建议的那样,我已经将计划更改为付费计划,并且我选择了一个动态计划。日志仍然没有说明功能在今天早上3点被激活。

  • 在过去的14个月里,我有一个Azure功能运行没有问题。每当在blob存储容器中创建新的blob时,它都使用BlobTrigger来运行。BLOB是间歇性创建的,因此该功能几乎完全依赖于冷启动(无需考虑延迟)。然而,截至一周前,BlobTrigger不再启动冷启动(如中所示,3天后该功能仍然没有运行)。但是当我访问门户中的功能时。为了唤醒它,BlobTrigger会为存储中的每个blob触发一次。