创建触发器变异错误

时间:2014-11-18 18:06:04

标签: oracle plsql plsqldeveloper

我需要创建一个触发器,每当您对表中的列进行更新时,他都会验证是否符合要求。 我创建了这个触发器:

       create or replace trigger trg_utente_activo 
    before update of idestado on utente
    for each row
    when (new.idestado = 3)
    declare
      ex_analises_geneticas EXCEPTION;
      flag boolean :=true;
    /*Vai buscar todas as analises obrigatorias*/
    cursor AnObri is
        select an_ob.codAnalise
        from AnalisesObrigatorias an_ob,analise a, tipoanalise ta
        where an_ob.codanalise like a.codanalise
        and a.idtipoanalise like ta.idtipoanalise 
        and ta.TipoAnaliseEnum like 3
        order by an_ob.codAnalise;
        AnalisesObrig AnObri%rowtype;
        /*Vai buscar todas as analises obrigatorias que o utente fez*/
    cursor AnObriUtent is
        select distinct req_a.codanalise
        from analise a,utente u,requisicao req,requisicao_analise req_a,analisesobrigatorias an_obr,tipoanalise ta
        where :new.idutente=req.idutente 
          and :new.idutente=u.idutente
          and an_obr.tipoutente=u.tipoutente
          and an_obr.codAnalise=a.codAnalise
          and req_a.codanalise=a.codanalise
          and ta.idtipoanalise=a.idtipoanalise 
          and ta.TipoAnaliseEnum = 3
          order by (req_a.codanalise);
        Analise AnObriUtent%ROWTYPE;

    begin 
    open AnObri;
    open AnObriUtent;
    loop
        fetch AnObri into AnalisesObrig;
        fetch AnObriUtent into Analise;
        if (Analise.codAnalise not like AnalisesObrig.codAnalise) then
           dbms_output.put_line(AnalisesObrig.codAnalise);
           flag:=false;
           dbms_output.put_line('flag ' || sys.diutil.bool_to_int(flag));
        else 
           dbms_output.put_line(AnalisesObrig.codAnalise || '-' || Analise.codAnalise);
           dbms_output.put_line('flag ' ||  sys.diutil.bool_to_int(flag));
        end if;   
    end loop;
      if (flag = true) then 
        update utente ut
          set ut.idestado = :new.idestado
        where idutente = idutente;
      else 
          raise ex_analises_geneticas;
      end if;
      close AnObriUtent;
      close AnObri;
      EXCEPTION 
       WHEN ex_analises_geneticas THEN 
         RAISE_APPLICATION_ERROR (-20001,'O utente não realizou todas as analises geneticas'); 
    END;

/

更新查询:

update utente
  set idestado=3
where idutente=1;

但是请给我这个错误信息:

ORA-06512: na "BD1415_DK9.TRG_UTENTE_ACTIVO", linha 12
ORA-06512: na "BD1415_DK9.TRG_UTENTE_ACTIVO", linha 27
ORA-04088: erro durante a execução do trigger 'BD1415_DK9.TRG_UTENTE_ACTIVO'
(ORA-04088: error during execution)
04091. 00000 -  "table %s.%s is mutating, trigger/function may not see it"

我尝试使用 pragma autonomous_transaction 但是给我错误 任何人都可以帮助我吗?

1 个答案:

答案 0 :(得分:0)

您的触发器正在更新utente.idestado,但它包含对同一列的更新,这意味着,如果验证通过,您将进入无限循环,即您的触发器将执行更新将触发触发器,触发器将执行更新,触发触发器等等...

你确定你不需要这样做:

create or replace trigger trg_utente_activo before update of idestado on utente

for each row
  when (new.idestado = 3)
    declare
      ex_analises_geneticas EXCEPTION;
      flag boolean :=true;

      /*Vai buscar todas as analises obrigatorias*/
      cursor AnObri is
        select an_ob.codAnalise
        from AnalisesObrigatorias an_ob,analise a, tipoanalise ta
        where an_ob.codanalise like a.codanalise
        and a.idtipoanalise like ta.idtipoanalise 
        and ta.TipoAnaliseEnum like 3
        order by an_ob.codAnalise;

      AnalisesObrig AnObri%rowtype;

      /*Vai buscar todas as analises obrigatorias que o utente fez*/
      cursor AnObriUtent is
        select distinct req_a.codanalise
        from analise a,utente u,requisicao req,requisicao_analise req_a,analisesobrigatorias an_obr,tipoanalise ta
        where :new.idutente=req.idutente 
        and :new.idutente=u.idutente
        and an_obr.tipoutente=u.tipoutente
        and an_obr.codAnalise=a.codAnalise
        and req_a.codanalise=a.codanalise
        and ta.idtipoanalise=a.idtipoanalise 
        and ta.TipoAnaliseEnum = 3
        order by (req_a.codanalise);

      Analise AnObriUtent%ROWTYPE;

      begin 
        open AnObri;
          open AnObriUtent;
            loop
              fetch AnObri into AnalisesObrig;
              fetch AnObriUtent into Analise;
                if (Analise.codAnalise not like AnalisesObrig.codAnalise) then
                  dbms_output.put_line(AnalisesObrig.codAnalise);
                  flag:=false;
                  dbms_output.put_line('flag ' || sys.diutil.bool_to_int(flag));
                else 
                  dbms_output.put_line(AnalisesObrig.codAnalise || '-' || Analise.codAnalise);
                  dbms_output.put_line('flag ' ||  sys.diutil.bool_to_int(flag));
                end if;   
            end loop;

            if (flag = false) then 
              raise ex_analises_geneticas;
            end if;
          close AnObriUtent;
        close AnObri;
      EXCEPTION 
        WHEN ex_analises_geneticas THEN 
          RAISE_APPLICATION_ERROR (-20001,'O utente não realizou todas as analises geneticas'); 
      END;
/