Проблема заключается в следующем: Я реализовал триггер в таблице с именем CLAN_AFFILIATI, который увеличивает (в случае отмены) и уменьшает (в случае отмены) атрибут (NUMAFFILIATI) другой таблицы с именем CLAN. то, что я хотел бы сделать, это заблокировать обновление NUMAFFILIATI Clan пользователем и подумал, что нужно выполнить еще один триггер на CLAN, который сделал это:
триггер на 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;
на 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;
но я делаю, сообщаю об ошибке:
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
как я могу решить эту проблему ....
Вероятно, это решение:
Я протестировал его с помощью следующих образцов таблиц:
CREATE TABLE CLAN_AFFILIATI(CLAN VARCHAR2(100),AFFILIATO VARCHAR2(100),RUOLO VARCHAR2(100));
CREATE TABLE CLAN (NOME VARCHAR2(100) ,NUMAFFILIATI NUMBER(10));
Вам нужен этот вспомогательный пакет.
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;
/
Триггер в таблице 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;
/
Триггер перед оператором в таблице 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;
/
Триггер после оператора в таблице 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;
/
Триггер вставки/удаления строки в таблице 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;
/
Сейчас работает это (без ORACLE- ИСКЛЮЧЕНИЕ):
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');
У меня нет с собой инструментов разработчика, но мне кажется, что вы ввязываетесь в своего рода проблему циклической зависимости. Когда ваш триггер CLAN_AFFILIATI поднимается, в нем вы выполняете обновление CLAN, которое вызывает второй триггер, у которого есть выбор из таблицы CLAN_AFFILIATI в блоке ELSE.
Возможно, также влияет вставка до (первый запрос) и после вставки (второй запрос).