Pular para o conteúdo
Visualizando 12 posts - 1 até 12 (de 12 do total)
  • Autor
    Posts
  • #93386
    gsmdf
    Participante

      Pessoal,

      Tenho o seguinte trecho da trigger, onde primeiro busco um cod, coloco na variável CGTP e depois seria algo do tipo:

      “Se o cod na variável CGTP não estiver dentre os codigos deste select, então levante exceção e aborte a operação”.
      Porém a implementação deste parte na trigger está dando erro. Como seria a maneira correta de implementar isso?

      IF (v_qtd <> 0)
      THEN
      SELECT cod_grupo_tipo_processo
      INTO cgtp
      FROM TIPO_PROCESSO
      WHERE COD =
      (SELECT cod_tipo_processo
      FROM HIST_TIPO_LOTE
      WHERE cod_lote = :new.cod_processo
      AND data_termino = NULL);
      /*Se o cod_grupo_tipo_processo do atual processo não constar entre as restrições então deve-se abortar a operação*/
      IF cgtp NOT IN
      (SELECT cod_grupo_tipo_processo
      FROM TIPO_EVENTO_PROC_GRUPO_TIPO TEPGT
      WHERE TEPGT.cod_tipo_evento = :new.cod_tipo_evento)
      THEN
      RAISE erro;
      END IF;
      END IF;

      Grato.

      #93395
      burga
      Participante

        Qual erro que está dando?

        #93410
        fsitja
        Participante

          Deixa eu adivinhar…

          fsitja puxa sua bola de cristal

          ORA-04091: table is mutating?

          #93415
          burga
          Participante

            hahahaha,

            Isso foi o que eu também imaginei Francisco, mas nem falei nada, preferi esperar a resposta do gsmdf.

            #93421
            fsitja
            Participante

              Posta o código todo da trigger (o cabeçalho é necessário) e o erro que deu para nós, por favor gsmdf, senão não tem como sugerir uma solução.

              #93426
              gsmdf
              Participante

                Foi mal galera, a trigger toda:
                O erro que o oracle retorna: PLS-00405: subquery not allowed in this context. Que é justamente a parte que eu usei “NOT IN” provavalmente de forma equivocada.


                /* Formatted on 29/3/2010 10:06:40 (QP5 v5.115.810.9015) */
                CREATE OR REPLACE TRIGGER TCU.TR_BIU_EVENTO_PROCESSO
                BEFORE INSERT OR UPDATE OF COD_TIPO_EVENTO, COD_PROCESSO
                ON EVENTO_PROCESSO
                FOR EACH ROW
                DECLARE
                /******************************************************************************
                NAME:
                PURPOSE: Verificar se há registro do tipo_evento_processo em TIPO_EVENTO_PROC_GRUPO_TIPO.Havendo restrições,
                deve-se checar se o processo atual respeita a restrição ou se o tipo de evento atual respeita a restrição do processo.
                Descrição demanda: Garantir por trigger biu em EVENTO_PROCESSO na coluna cod_tipo_evento, cod_processo
                Que: se o tipo_evento_processo(evento_processo(cod_evento).cod_tipo_evento) tiver registro
                em TIPO_EVENTO_PROC_GRUPO_TIPO, apenas permitir evento para processo (cod_processo) cujo tipo seja do grupo indicado.
                (como identificar grupo do tipo atual do processo => tipo_processo(hist_tipo_lote(cod_processo).cod_tipo_processo, onde data_termino is null).
                cod_grupo_tipo_processo

                REVISIONS:
                Date Author Description
                ---------- --------------- ------------------------------------
                26/3/2010 Guilherme Marques 1. Created this trigger.

                ******************************************************************************/
                v_qtd NUMBER;
                v_se_critica BOOLEAN;
                cgtp TIPO_PROCESSO.COD_GRUPO_TIPO_PROCESSO%TYPE;
                erro EXCEPTION;
                BEGIN
                v_se_critica := FALSE;

                IF (:new.cod_tipo_evento IS NOT NULL AND :new.cod_processo IS NOT NULL)
                THEN
                /Conferir se o novo valor do campo cod_tipo_evento é diferente do antigo/
                IF (UPDATING
                AND ( (:new.COD_TIPO_EVENTO :old.COD_TIPO_EVENTO)
                OR (:new.COD_TIPO_EVENTO IS NOT NULL
                AND:old.COD_TIPO_EVENTO IS NULL)))
                THEN
                v_se_critica := TRUE;
                END IF;

                  /*Tratando o campo COD_PROCESSO*/
                
                
                  IF ( (UPDATING)
                      AND ( (:new.COD_PROCESSO  :old.COD_PROCESSO)
                           OR (:new.COD_PROCESSO IS NOT NULL
                               AND:old.COD_PROCESSO IS NULL)))
                  THEN
                     v_se_critica := TRUE;
                  END IF;
                
                  IF INSERTING
                  THEN
                     v_se_critica := TRUE;
                  END IF;
                

                END IF;

                IF (v_se_critica = TRUE)
                THEN
                SELECT COUNT ( * )
                INTO v_qtd
                FROM TIPO_EVENTO_PROC_GRUPO_TIPO TEPGT
                WHERE TEPGT.cod_tipo_evento = :new.cod_tipo_evento;

                  /*No caso de haver restrições então continua a trigger
                    e busca-se o cod_grupo_tipo_processo atual do processo      
                  */
                  IF (v_qtd  0)
                  THEN
                     SELECT   cod_grupo_tipo_processo
                       INTO   cgtp
                       FROM   TIPO_PROCESSO
                      WHERE   COD =
                                 (SELECT   cod_tipo_processo
                                    FROM   HIST_TIPO_LOTE
                                   WHERE   cod_lote = :new.cod_processo
                                           AND data_termino = NULL);
                     /*Se o cod_grupo_tipo_processo do atual processo não constar entre as restrições então deve-se abortar a operação*/
                     IF cgtp NOT IN
                              (SELECT   cod_grupo_tipo_processo
                                 FROM   TIPO_EVENTO_PROC_GRUPO_TIPO TEPGT
                                WHERE   TEPGT.cod_tipo_evento = :new.cod_tipo_evento)
                     THEN
                        RAISE erro;
                     END IF;
                  END IF;
                

                END IF;
                EXCEPTION
                WHEN erro
                THEN
                RAISE_APPLICATION_ERROR (
                -20001,
                'Tipo de evento não permitido para este processo! Operaração cancelada! '
                );
                END;

                #93429
                fsitja
                Participante

                  É isso mesmo, a subquery no NOT IN. Tenta o seguinte no lugar daquele trecho:

                  IF (v_qtd 0)
                  THEN
                  BEGIN
                  SELECT cod_grupo_tipo_processo
                  INTO cgtp
                  FROM tipo_processo
                  WHERE cod = (SELECT cod_tipo_processo
                  FROM hist_tipo_lote
                  WHERE cod_lote = :new.cod_processo
                  AND data_termino = NULL)
                  AND cod_grupo_tipo_processo NOT IN
                  (SELECT cod_grupo_tipo_processo
                  FROM tipo_evento_proc_grupo_tipo tepgt
                  WHERE tepgt.cod_tipo_evento = :new.cod_tipo_evento);
                  EXCEPTION
                  /Se o cod_grupo_tipo_processo do atual processo não constar entre as restrições então deve-se abortar a operação/
                  WHEN no_data_found THEN
                  THEN RAISE erro;
                  END;
                  END IF;

                  #93431
                  gsmdf
                  Participante

                    Hmm, entendi.
                    Ficou assim o código:
                    O Exception when no_data_found é pra ficar lá embaixo na area e EXCEPTIONS msm né?
                    Vlw!


                    /* Formatted on 30/3/2010 09:37:48 (QP5 v5.115.810.9015) */
                    CREATE OR REPLACE TRIGGER TCU.TR_BIU_EVENTO_PROCESSO
                    BEFORE INSERT OR UPDATE OF COD_TIPO_EVENTO, COD_PROCESSO
                    ON EVENTO_PROCESSO
                    FOR EACH ROW
                    DECLARE
                    /******************************************************************************
                    NAME:
                    PURPOSE: Verificar se há registro do tipo_evento_processo em TIPO_EVENTO_PROC_GRUPO_TIPO.Havendo restrições,
                    deve-se checar se o processo atual respeita a restrição ou se o tipo de evento atual respeita a restrição do processo.
                    Descrição demanda: Garantir por trigger biu em EVENTO_PROCESSO na coluna cod_tipo_evento, cod_processo
                    Que: se o tipo_evento_processo(evento_processo(cod_evento).cod_tipo_evento) tiver registro
                    em TIPO_EVENTO_PROC_GRUPO_TIPO, apenas permitir evento para processo (cod_processo) cujo tipo seja do grupo indicado.
                    (como identificar grupo do tipo atual do processo => tipo_processo(hist_tipo_lote(cod_processo).cod_tipo_processo, onde data_termino is null).
                    cod_grupo_tipo_processo

                    REVISIONS:
                    Date Author Description
                    ---------- --------------- ------------------------------------
                    26/3/2010 Guilherme Marques 1. Created this trigger.

                    ******************************************************************************/
                    v_qtd NUMBER;
                    v_se_critica BOOLEAN;
                    cgtp TIPO_PROCESSO.COD_GRUPO_TIPO_PROCESSO%TYPE;
                    erro EXCEPTION;
                    BEGIN
                    v_se_critica := FALSE;

                    IF (:new.cod_tipo_evento IS NOT NULL AND :new.cod_processo IS NOT NULL)
                    THEN
                    /Conferir se o novo valor do campo cod_tipo_evento é diferente do antigo/
                    IF (UPDATING
                    AND ( (:new.COD_TIPO_EVENTO :old.COD_TIPO_EVENTO)
                    OR (:new.COD_TIPO_EVENTO IS NOT NULL
                    AND:old.COD_TIPO_EVENTO IS NULL)))
                    THEN
                    v_se_critica := TRUE;
                    END IF;

                      /*Tratando o campo COD_PROCESSO*/
                    
                    
                      IF ( (UPDATING)
                          AND ( (:new.COD_PROCESSO  :old.COD_PROCESSO)
                               OR (:new.COD_PROCESSO IS NOT NULL
                                   AND:old.COD_PROCESSO IS NULL)))
                      THEN
                         v_se_critica := TRUE;
                      END IF;
                    
                      IF INSERTING
                      THEN
                         v_se_critica := TRUE;
                      END IF;
                    

                    END IF;

                    IF (v_se_critica = TRUE)
                    THEN
                    SELECT COUNT ( * )
                    INTO v_qtd
                    FROM TIPO_EVENTO_PROC_GRUPO_TIPO TEPGT
                    WHERE TEPGT.cod_tipo_evento = :new.cod_tipo_evento;

                      /*No caso de haver restrições então continua a trigger
                        e busca-se o cod_grupo_tipo_processo atual do processo
                      */
                      IF (v_qtd  0)
                      THEN
                         SELECT   cod_grupo_tipo_processo
                           INTO   cgtp
                           FROM   TIPO_PROCESSO
                          WHERE   COD =
                                     (SELECT   cod_tipo_processo
                                        FROM   HIST_TIPO_LOTE
                                       WHERE   cod_lote = :new.cod_processo
                                               AND data_termino = NULL)
                                  AND cod_grupo_tipo_processo NOT IN
                             (SELECT cod_grupo_tipo_processo
                                    FROM tipo_evento_proc_grupo_tipo tepgt
                                   WHERE tepgt.cod_tipo_evento = :new.cod_tipo_evento);         
                      END IF;     
                    

                    END IF;
                    EXCEPTION
                    /Se o cod_grupo_tipo_processo do atual processo não constar entre as restrições então deve-se abortar a operação/
                    WHEN no_data_found THEN
                    RAISE erro;

                    WHEN erro
                    THEN
                    RAISE_APPLICATION_ERROR (
                    -20001,
                    'Tipo de evento não permitido para este processo! Operaração cancelada! '
                    );
                    END;

                    #93456
                    fsitja
                    Participante

                      Era para ficar somente naquele select mesmo, como um sub-bloco, pois senão todo e qualquer no_data_found (mesmo em outros selects) vão causar o tratamento de RAISE erro; o que não seria correto para a lógica que você precisa.

                      #93459
                      gsmdf
                      Participante

                        Hm, entendo, suspeitei disso.
                        Então coloquei o exception no sub-bloco como você falou, porém está dando erro:

                        IF (v_se_critica = TRUE)
                        THEN
                        SELECT COUNT ( * )
                        INTO v_qtd
                        FROM TIPO_EVENTO_PROC_GRUPO_TIPO TEPGT
                        WHERE TEPGT.cod_tipo_evento = :new.cod_tipo_evento;

                          /*No caso de haver restrições então continua a trigger
                            e busca-se o cod_grupo_tipo_processo atual do processo
                          */
                          IF (v_qtd  0)
                          THEN
                             SELECT   cod_grupo_tipo_processo
                               INTO   cgtp
                               FROM   TIPO_PROCESSO
                              WHERE   COD =
                                         (SELECT   cod_tipo_processo
                                            FROM   HIST_TIPO_LOTE
                                           WHERE   cod_lote = :new.cod_processo
                                                   AND data_termino = NULL)
                                      AND cod_grupo_tipo_processo NOT IN
                                 (SELECT cod_grupo_tipo_processo
                                        FROM tipo_evento_proc_grupo_tipo tepgt
                                       WHERE tepgt.cod_tipo_evento = :new.cod_tipo_evento);
                        
                                       EXCEPTION
                                /*Se o cod_grupo_tipo_processo do atual processo não constar entre as restrições então deve-se abortar a operação*/
                                WHEN no_data_found THEN
                                RAISE erro;
                                END;
                        
                        
                                    END IF;
                        

                        END IF;

                        Não seria o caso de “IF (NO_DATA_FOUND) THEN RAISE ERRO; ?

                        #93461
                        fsitja
                        Participante

                          O select precisa ficar aninhado dentro de um sub-bloco “begin begin end; end;”


                          DECLARE
                          vx number;
                          erro exception;
                          BEGIN
                          NULL;
                          NULL;
                          BEGIN
                          SELECT 1 x into vx FROM DUAL where 1 = 0;
                          EXCEPTION
                          WHEN NO_DATA_FOUND THEN
                          RAISE ERRO;
                          END;
                          EXCEPTION
                          WHEN ERRO THEN
                          DBMS_OUTPUT.PUT_LINE('DEU ERRO E ENTROU NO EXCEPTION');
                          END;

                          #93537
                          gsmdf
                          Participante

                            Entendi, que não sabia esse conceito de sub-bloco e de colocar mais de um bloco exception, obrigado!

                          Visualizando 12 posts - 1 até 12 (de 12 do total)
                          • Você deve fazer login para responder a este tópico.