oracle 表正在发生变化,触发器无法读取或修改它

lx0bsm1f  于 2023-06-05  发布在  Oracle
关注(0)|答案(1)|浏览(640)

表正在发生变化,触发器无法读取或修改它,ORACLE SQL
我有表传票(小时,DataJogo,EquipaID,NIF,MinutesPlayed),其中分钟通常是90。然而,我有一个表(Hour,DataJogo,EquipaID,IF,Minute,TipoAcaoID),问题是,如果一个玩家在第32分钟有一张红牌(ActionTypeID(TipoAcaoID)= 8),召唤表应该将MinutesPlayed更改为32。
这是我的触发器:

CREATE OR REPLACE TRIGGER check_if_red_card_or_two_yellows_before_insert_new_summon
AFTER INSERT OR UPDATE ON ACOES
FOR EACH ROW
    DECLARE
    ContagemAmarelos INT;
    ContagemVermelhos INT;
BEGIN
    SELECT COUNT(*) INTO ContagemAmarelos
    FROM Acoes
    WHERE NIF = :NEW.NIF AND TipoAcaoID = 7 AND DataJogo = :NEW.DataJogo AND Hora = :NEW.Hora;
    
    SELECT COUNT(*) INTO ContagemVermelhos
    FROM Acoes
    WHERE NIF = :NEW.NIF AND TipoAcaoID = 8 AND DataJogo = :NEW.DataJogo AND Hora = :NEW.Hora;
    
    IF ContagemAmarelos = 2 THEN
        UPDATE CONVOCATORIA
        SET MinutosJogados = (
            SELECT Minuto
            FROM Acoes
            WHERE NIF = :NEW.NIF AND TipoAcaoID = 7 AND DataJogo = :NEW.DataJogo AND Hora = :NEW.Hora
        );
            
    ELSIF ContagemVermelhos = 1 THEN
        UPDATE CONVOCATORIA
        SET MinutosJogados = (
            SELECT Minuto
            FROM Acoes 
            WHERE NIF = :NEW.NIF AND TipoAcaoID = 8 AND DataJogo = :NEW.DataJogo AND Hora = :NEW.Hora
        );
    END IF;
END;
/

触发器编译,但是当我尝试将值插入到操作中时,我在标题中得到错误。

qhhrdooz

qhhrdooz1#

可以在一条语句中插入多行。也可以在一条语句中更新多行。MERGE语句可以一次插入和更新多行。
现在想象一下,当触发器执行时会发生什么,行的顺序是随机的,所以触发器以随机顺序在每行上执行。
这个“Table is mutating”错误可以理解为Oracle告诉你的:“我不能保证你的代码是确定性的。如果您在两个具有相同数据的数据库中执行相同的UPDATE/MERGE/INSERT,则结果可能不同。
如何克服这种情况的常见方法:

  • 将业务逻辑放入具有PRAGMA AUTONOMOUS TRANSACTION注解的PROCEDURE中。这样的过程将无法看到任何未提交的数据。所以在你的情况下,它不会帮助。
  • 使用复合触发器,在触发器的BEFORE部分收集必要的数据,将它们存储在局部变量中,并在触发器的AFTER部分应用更改。
  • 同时使用BEFOREAFTER触发器,将数据存储在包变量中,并在AFTER触发器中应用更改。

注意:您需要收集的数据必须是某种哈希Map(TABLE OF datatype [NOT NULL] INDEX BY ...;)。因此可以捕获语句修改的每一行的更改。

相关问题