- Este tópico contém 11 respostas, 3 vozes e foi atualizado pela última vez 15 anos, 11 meses atrás por
gsmdf.
-
AutorPosts
-
29 de março de 2010 às 6:32 pm #93386
gsmdf
ParticipantePessoal,
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.
29 de março de 2010 às 8:37 pm #93395burga
ParticipanteQual erro que está dando?
29 de março de 2010 às 11:17 pm #93410fsitja
ParticipanteDeixa eu adivinhar…
fsitja puxa sua bola de cristal
ORA-04091: table is mutating?
30 de março de 2010 às 12:00 am #93415burga
Participantehahahaha,
Isso foi o que eu também imaginei Francisco, mas nem falei nada, preferi esperar a resposta do gsmdf.
30 de março de 2010 às 1:07 am #93421fsitja
ParticipantePosta 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.
30 de março de 2010 às 4:16 pm #93426gsmdf
ParticipanteFoi 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_processoREVISIONS:
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;30 de março de 2010 às 4:48 pm #93429fsitja
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;
30 de março de 2010 às 5:42 pm #93431gsmdf
ParticipanteHmm, 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_processoREVISIONS:
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;31 de março de 2010 às 1:17 am #93456fsitja
ParticipanteEra 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.
31 de março de 2010 às 4:31 pm #93459gsmdf
ParticipanteHm, 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; ?
31 de março de 2010 às 6:53 pm #93461fsitja
ParticipanteO 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;
5 de abril de 2010 às 5:03 pm #93537gsmdf
ParticipanteEntendi, que não sabia esse conceito de sub-bloco e de colocar mais de um bloco exception, obrigado!
-
AutorPosts
- Você deve fazer login para responder a este tópico.