Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql oracle中的触发器问题_Sql_Oracle_Plsql_Triggers_Ora 04091 - Fatal编程技术网

Sql oracle中的触发器问题

Sql oracle中的触发器问题,sql,oracle,plsql,triggers,ora-04091,Sql,Oracle,Plsql,Triggers,Ora 04091,问题是: 我在名为CLAN_AFFILIATI的表上实现了一个触发器,它增加(如果是inseriemento)并减少(如果是取消)另一个名为CLAN的表的属性(NUMAFFILIATI)。我要做的是阻止用户更新Clan的NUMAFFILIATI,并曾想过在Clan上触发另一个触发: 触发氏族阿菲利亚蒂(氏族瓦查尔、阿菲利亚托瓦查尔、鲁奥洛瓦查尔) 氏族上的触发器(名称VARCHAR,numafiliati整数) 如何解决此问题……更改第一个触发器“aggiornamentonumafiliati

问题是: 我在名为CLAN_AFFILIATI的表上实现了一个触发器,它增加(如果是inseriemento)并减少(如果是取消)另一个名为CLAN的表的属性(NUMAFFILIATI)。我要做的是阻止用户更新Clan的NUMAFFILIATI,并曾想过在Clan上触发另一个触发:

触发氏族阿菲利亚蒂(氏族瓦查尔、阿菲利亚托瓦查尔、鲁奥洛瓦查尔)

氏族上的触发器(名称VARCHAR,numafiliati整数)


如何解决此问题……

更改第一个触发器“aggiornamentonumafiliati”,使其不会立即尝试更新clan,而是将名称(NOME)存储在包中的PL/SQL表中;然后,创建一个AFTER INSERT或DELETE(但不带FOR EACH ROW子句)触发器,从包中读取PL/SQL表并相应地更新clan。

我没有带开发人员工具,但在我看来,您似乎陷入了某种循环依赖性问题。当触发CLAN_AFFILIATI触发器时,在其中执行CLAN的更新,该更新调用第二个触发器,该触发器在ELSE块中的CLAN_AFFILIATI表中有一个select


可能插入前(第一次查询)和插入后(第二次查询)也有影响。

这是一种可能的解决方案:

我使用以下示例表对其进行了测试:

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;
/
氏族表上的触发器:

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表上的After语句触发器:

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;
/
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;
/
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;
/
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;
/
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;
/
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):


ORA-04091也被称为“突变表”错误-基本上,行触发器无法查询或更改触发器操作的表

@Martin的回答是关于如何解决此问题的经典描述,但如果您使用的是Oracle 11+,则可以使用来完成相同的任务


分享和享受。

您能提供准确的Oracle错误代码吗?错误ORA-04091:表ANTONIO.CLAN_AFFILIATI正在修改,触发器/函数无法读取ORA-06512:位于“ANTONIO.Modificanumafiliati”,第10行ORA-04088:执行触发器“ANTONIO.Modificanumafiliati”时的错误ORA-06512:位于“ANTONIO.AggiorNamentonumafiliati”,第12行ORA-04088:执行触发器“ANTONIO.aggiornamentonumafiliati”时出错如何创建PL/SQL表?参见martin的回答,他比我更勤奋,因为你的回答很好,几乎所有操作都很完美,唯一的问题是取消,如果从CLAN_AFFILIATIFIRST中删除一行-引发触发“TRG_CLAN_AFFILIATI_BEFORE STMT”-Oracle在表中的任何数据操作之前引发该行,则不会更新ie NUMAFFILIATI。这是一个必须清除数组(STORE_NOMES.g_array_NOMES)的地方,否则它将无法工作。第二个-是引发触发器“aggiornamentonumafiliati”,有一个地方存储数组中的NOMES(STORE_NOMES.g_array_NOMES)及其操作(INSERT或DELETE)。第三个(也是最后一个)是在语句触发“TRG_CLAN_AFFILIATI_after_STMT”之后提出的,Oracle在完成所有DML(数据制造)之后提出了该语句。在这里,您可以对CLAN表调用update。Oracle类型的STORE_NOMES.g_array_NOMES类似于内存(记住执行了哪些名称和操作)。但我注意到当表中的一行被清除时出现了一个问题CLAN_AFFILIATI NUMAFFILIATI没有更新。对不起,我想知道query:)我查看了它。我会让你知道。。。给我30分钟。。。
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');