Plsql 在后行触发器中更改表问题

Plsql 在后行触发器中更改表问题,plsql,oracle11g,package,triggers,mutating-table,Plsql,Oracle11g,Package,Triggers,Mutating Table,我创建了一个包含一个过程和一个函数的包。 函数由表REZULTAT上每行之后的insert触发器调用 create or replace trigger rezultat_compound for insert on rezultat compound trigger v_igid rezultat.igra_id%type; v_reid rezultat.id%type; v_jck rezultat.jo

我创建了一个包含一个过程和一个函数的包。 函数由表REZULTAT上每行之后的insert触发器调用

create or replace trigger rezultat_compound
for insert on rezultat
compound trigger
 v_igid              rezultat.igra_id%type;
 v_reid              rezultat.id%type;
 v_jck               rezultat.jocker_broj%type;
 cursor cur_type is  rezultat%rowtype;
before each row is
begin
 v_reid:=rezultat_seq.nextval;
 :new.id:=v_reid;
 v_igid:=:new.igra_id;
end before each row;

after each row is
begin
 v_jck:=loto_7_47_pck.getJockerBroj(v_igid);
end after each row;

end rezultat_compound;
函数应该为插入的行计算其中一列,其输入参数是插入行的ID,在使用记录类型进行计算之前,我使用该ID将特定插入行选择到记录类型中

function                getJockerBroj
( i_igra_id             igra.id%type
)
return                  rezultat.jocker_broj%type
is
 v_jocker            rezultat.jocker_broj%type;
 rezultat_rec        brojevi_type; 
begin
select  br1
     , br2
     , br3
     , br4
     , br5
     , br6
     , br7
     ,dopunski_broj
into   rezultat_rec
from   rezultat
where  igra_id=i_igra_id;
v_jocker:=
      (  substr(to_char(rezultat_rec.br1),-1, 1) 
      || substr(to_char(rezultat_rec.br2),-1, 1) 
      || substr(to_char(rezultat_rec.br3),-1, 1)
      || substr(to_char(rezultat_rec.br4),-1, 1)
      || substr(to_char(rezultat_rec.br5),-1, 1)
      || substr(to_char(rezultat_rec.br6),-1, 1)
      || substr(to_char(rezultat_rec.br7),-1, 1)
      )
      ;    
 return v_jocker;
 end;
这显然会导致变异表错误,即使在每行插入后调用该函数也是如此

如何绕过此问题并使用该函数中插入的每一行进行计算?

不允许触发器(以及触发器调用的任何函数)查询
rezultat
表,因为触发器是
rezultat
表上定义的行级别。正如您所发现的,这样做会导致一个变异表异常

通常,您希望对逻辑进行编码,以便只引用
:new
伪记录中的数据。例如,在本例中,您可以定义函数以接受7个参数,并从触发器传递这些参数值。差不多

CREATE OR REPLACE FUNCTION getJockerBroj (
  p_br1 in rezultat.br1%type,
  p_br2 in rezultat.br2%type,
  p_br3 in rezultat.br3%type,
  p_br4 in rezultat.br4%type,
  p_br5 in rezultat.br5%type,
  p_br6 in rezultat.br6%type,
  p_br7 in rezultat.br7%type
)
  RETURN rezultat.jocker_broj%type
IS
BEGIN
  RETURN substr(to_char(p_br1),-1, 1) 
      || substr(to_char(p_br2),-1, 1) 
      || substr(to_char(p_br3),-1, 1)
      || substr(to_char(p_br4),-1, 1)
      || substr(to_char(p_br5),-1, 1)
      || substr(to_char(p_br6),-1, 1)
      || substr(to_char(p_br7),-1, 1);
END;
v_jck:=loto_7_47_pck.getJockerBroj(:new.br1, 
                                   :new.br2,
                                   :new.br3,
                                   :new.br4,
                                   :new.br5,
                                   :new.br6,
                                   :new.br7);
你的扳机会这样做

CREATE OR REPLACE FUNCTION getJockerBroj (
  p_br1 in rezultat.br1%type,
  p_br2 in rezultat.br2%type,
  p_br3 in rezultat.br3%type,
  p_br4 in rezultat.br4%type,
  p_br5 in rezultat.br5%type,
  p_br6 in rezultat.br6%type,
  p_br7 in rezultat.br7%type
)
  RETURN rezultat.jocker_broj%type
IS
BEGIN
  RETURN substr(to_char(p_br1),-1, 1) 
      || substr(to_char(p_br2),-1, 1) 
      || substr(to_char(p_br3),-1, 1)
      || substr(to_char(p_br4),-1, 1)
      || substr(to_char(p_br5),-1, 1)
      || substr(to_char(p_br6),-1, 1)
      || substr(to_char(p_br7),-1, 1);
END;
v_jck:=loto_7_47_pck.getJockerBroj(:new.br1, 
                                   :new.br2,
                                   :new.br3,
                                   :new.br4,
                                   :new.br5,
                                   :new.br6,
                                   :new.br7);

谢谢你的快速回复。这很有效,但我还有其他问题。我在包中有另一个过程,它生成brX值并将它们相应地插入到REZULTAT中。这个过程实际上触发了insert触发器。由于该过程(doGenerateValues)和函数getJockerBroj在同一个包中,是否有方法将插入的brX值从过程传递到函数?(就像使用游标或记录一样)@user3885274-可以吗?当然,您可以创建一个包全局变量并使用它来传递信息。但是,您肯定希望避免这种情况,因为它使您的应用程序很难跟踪。你对函数的结果做了什么?您确定不能将函数调用移到过程中,而不是将其放在触发器中吗?触发器中的应用程序逻辑通常使遵循应用程序正在实现的逻辑变得困难。