甲骨文触发器的问题 [英] problem with trigger in oracle
问题描述
问题是这样的: 我在名为CLAN_AFFILIATI的表上实现了一个触发器,该触发器增加(如果是inseriemento)并减小(在取消的情况下)另一个CLAN表的属性(NUMAFFILIATI).我要做的是阻止用户对Clan的更新NUMAFFILIATI,并曾考虑在CLAN上进行另一次尝试:
the problem is this : I implemented a trigger on the table called CLAN_AFFILIATI that increases (if inseriemento) and decreases (in case of cancellation) an attribute (NUMAFFILIATI) of another table called CLAN. what I would do is block the update NUMAFFILIATI of Clan by the user and had thought to r another trigge on CLAN that did this:
在CLAN_AFFILIATI(CLAN VARCHAR,AFFILIATO VARCHAR,RUOLO VARCHAR)上触发
trigger on 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)
trigger on 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
我该如何解决这个问题....
how can I solve this problem ....
推荐答案
这可能是解决方案:
我使用以下示例表对其进行了测试:
I tested it with this sample tables:
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表上的语句触发之前:
Before statement trigger on CLAN_AFFILIATI table:
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表上的语句触发之后:
After statement trigger on CLAN_AFFILIATI table:
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表上的行插入/删除触发器:
Row Insert/Delete trigger on CLAN_AFFILIATI table:
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-EXCEPTION):
Now working this (without 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');
这篇关于甲骨文触发器的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!