trigger solucion ora ejemplos compuestos compound 11g sql oracle plsql triggers ora-04091

sql - solucion - problema con el gatillo en el oráculo



trigger pl sql (4)

Cambie el primer activador "AggiornamentoNumAffiliati" para que no intente actualizar el clan inmediatamente, pero almacene el nombre (NOME) en una tabla PL / SQL dentro de un paquete; luego, crea un desencadenante DESPUÉS DE INSERTAR O ELIMINAR (pero sin la cláusula FOR E HUN CLOT) que lee la tabla PL / SQL del paquete y actualiza los CLAN en consecuencia.

el problema es este: Implementé un disparador en la tabla llamado CLAN_AFFILIATI que aumenta (si hay inseriemento) y disminuye (en caso de cancelación) un atributo (NUMAFFILIATI) de otra tabla llamada CLAN. lo que haría sería bloquear la actualización NUMAFFILIATI de Clan por el usuario y había pensado en otra activación en CLAN que hiciera esto:

desencadenar en CLAN_AFFILIATI (CLAN VARCHAR, AFFILIATO VARCHAR, RUOLO VARCHAR)

CREATE OR REPLACE TRIGGER "AggiornamentoNumAffiliati" AFTER INSERT OR DELETE ON CLAN_AFFILIATI FOR EACH ROW DECLARE CLAN_APPARTENENZA VARCHAR(20); BEGIN IF INSERTING THEN SELECT NOME INTO CLAN_APPARTENENZA FROM CLAN WHERE NOME=:new.CLAN; UPDATE CLAN SET NUMAFFILIATI=NUMAFFILIATI+1 WHERE CLAN_APPARTENENZA=NOME; ELSE SELECT NOME INTO CLAN_APPARTENENZA FROM CLAN WHERE NOME=:old.CLAN; UPDATE CLAN SET NUMAFFILIATI=NUMAFFILIATI-1 WHERE CLAN_APPARTENENZA=NOME; END IF; END;

desencadenar en CLAN (NAME VARCHAR, NUMAFFILIATI INTEGER)

CREATE OR REPLACE TRIGGER "ModificaNumAffiliati" BEFORE INSERT OR UPDATE OF NUMAFFILIATI ON CLAN FOR EACH ROW DECLARE CONT NUMBER:=0; BEGIN IF INSERTING THEN IF :new.NUMAFFILIATI <> 0 THEN RAISE_APPLICATION_ERROR(-20016,''NUMERO ERRATO''); END IF; ELSE SELECT COUNT(*) INTO CONT FROM CLAN_AFFILIATI WHERE :old.NOME=CLAN; IF CONT <> :new.NUMAFFILIATI THEN RAISE_APPLICATION_ERROR(-20017,''NUMERO ERRATO''); END IF; END IF; END;

pero lo que estoy haciendo es informar un error:

error ORA-04091: Table ANTONIO.CLAN_AFFILIATI is being modified, the trigger / function can not read ORA-06512: at "ANTONIO.ModificaNumAffiliati", line 10 ORA-04088: error during execution of trigger ''ANTONIO.ModificaNumAffiliati'' ORA-06512: at "ANTONIO.AggiornamentoNumAffiliati", line 12 ORA-04088: error during execution of trigger ''ANTONIO.AggiornamentoNumAffiliati

Como puedó resolver esté problema ....


Esta es una solución viable:

Lo probé con estas tablas de muestra:

CREATE TABLE CLAN_AFFILIATI(CLAN VARCHAR2(100),AFFILIATO VARCHAR2(100),RUOLO VARCHAR2(100)); CREATE TABLE CLAN (NOME VARCHAR2(100) ,NUMAFFILIATI NUMBER(10));

Necesitas este paquete de ayuda.

CREATE OR REPLACE PACKAGE STORE_NOMES AS TYPE record_nomes IS RECORD ( nome VARCHAR2(100), operation VARCHAR2(100) -- insert or delete ); TYPE array_type_nomes IS TABLE OF record_nomes INDEX BY BINARY_INTEGER; g_array_nomes array_type_nomes; END STORE_NOMES; /

Disparador en la tabla CLAN:

CREATE OR REPLACE TRIGGER MODIFICANUMAFFILIATI BEFORE INSERT OR UPDATE OF NUMAFFILIATI ON CLAN FOR EACH ROW DECLARE l_CONT NUMBER:=0; BEGIN IF INSERTING THEN -- prevent inserting <> 0 IF :new.NUMAFFILIATI <> 0 THEN RAISE_APPLICATION_ERROR(-20016,''NUMERO ERRATO''); END IF; ELSE SELECT COUNT(*) INTO l_CONT FROM CLAN_AFFILIATI WHERE CLAN = :old.NOME; IF l_CONT <> :new.NUMAFFILIATI THEN RAISE_APPLICATION_ERROR(-20017,''NUMERO ERRATO''); END IF; END IF; END; /

Antes del desencadenante de declaración en la tabla CLAN_AFFILIATI:

CREATE OR REPLACE TRIGGER TRG_CLAN_AFFILIATI_BEFORE_STMT BEFORE INSERT OR DELETE ON CLAN_AFFILIATI DECLARE BEGIN STORE_NOMES.g_array_nomes.DELETE; END; /

Después del desencadenante de declaración en la tabla CLAN_AFFILIATI:

CREATE OR REPLACE TRIGGER TRG_CLAN_AFFILIATI_AFTER_STMT AFTER INSERT OR DELETE ON CLAN_AFFILIATI DECLARE BEGIN FOR i IN STORE_NOMES.g_array_nomes.FIRST..STORE_NOMES.g_array_nomes.LAST LOOP IF(STORE_NOMES.g_array_nomes(i).operation = ''INSERTING'') THEN UPDATE CLAN SET NUMAFFILIATI=NUMAFFILIATI+1 WHERE NOME = STORE_NOMES.g_array_nomes(i).NOME; ELSIF(STORE_NOMES.g_array_nomes(i).operation = ''DELETING'') THEN UPDATE CLAN SET NUMAFFILIATI=NUMAFFILIATI-1 WHERE NOME = STORE_NOMES.g_array_nomes(i).NOME; END IF; END LOOP; END; /

Insertar fila / Eliminar activador en la tabla CLAN_AFFILIATI:

CREATE OR REPLACE TRIGGER AGGIORNAMENTONUMAFFILIATI BEFORE INSERT OR DELETE ON CLAN_AFFILIATI FOR EACH ROW DECLARE l_CLAN_APPARTENENZA VARCHAR(20); BEGIN IF INSERTING THEN SELECT NOME INTO l_CLAN_APPARTENENZA FROM CLAN WHERE NOME = :new.CLAN; STORE_NOMES.g_array_nomes(STORE_NOMES.g_array_nomes.COUNT).nome := :new.CLAN; STORE_NOMES.g_array_nomes(STORE_NOMES.g_array_nomes.LAST).operation := ''INSERTING''; ELSE SELECT NOME INTO l_CLAN_APPARTENENZA FROM CLAN WHERE NOME = :old.CLAN; STORE_NOMES.g_array_nomes(STORE_NOMES.g_array_nomes.COUNT).nome := :old.CLAN; STORE_NOMES.g_array_nomes(STORE_NOMES.g_array_nomes.LAST).operation := ''DELETING''; END IF; END; /

Ahora trabajando esto (sin ORACLE-EXCEPTION):

INSERT INTO CLAN(NOME, NUMAFFILIATI) VALUES(''Antonio'', 0); INSERT INTO CLAN_AFFILIATI(CLAN,AFFILIATO,RUOLO) values(''Antonio'',''Affiliato1'',''Ruolo1''); INSERT INTO CLAN_AFFILIATI(CLAN,AFFILIATO,RUOLO) values(''Antonio'',''Affiliato2'',''Ruolo2'');


No tengo mis herramientas de desarrollador conmigo, pero me parece como si te metieras en una especie de dependencia cíclica. Cuando se activa su activador CLAN_AFFILIATI, en él realiza una actualización de CLAN que llama al segundo activador, que tiene una selección de la tabla CLAN_AFFILIATI en el bloque ELSE.

Tal vez la inserción anterior (primera consulta) y luego de la inserción (segunda consulta) también tengan un efecto.


ORA-04091 también se conoce como un error de "tabla de mutación": básicamente, los activadores de fila no pueden consultar o alterar la tabla en la que opera el activador.

La respuesta de @Martin es la descripción clásica de cómo solucionar este problema, pero si usa Oracle 11+ puede usar un activador compuesto para hacer lo mismo.

Comparte y Disfruta.