Oracle
 sql >> Base de données >  >> RDS >> Oracle

ORA-04091 :la table [blah] est en train de muter, le déclencheur/la fonction peut ne pas la voir

Je pense que je ne suis pas d'accord avec votre description de ce que le déclencheur essaie de faire. Il me semble qu'il est destiné à appliquer cette règle métier :pour une valeur donnée de t1_appnt_event, une seule ligne peut avoir une valeur non NULL oft1_prnt_t1_pk à la fois. (Peu importe qu'ils aient ou non la même valeur dans la deuxième colonne.)

Fait intéressant, il est défini pour UPDATE OF t1_appnt_event mais pas pour l'autre colonne, donc je pense que quelqu'un pourrait enfreindre la règle en mettant à jour la deuxième colonne, à moins qu'il n'y ait un déclencheur séparé pour cette colonne.

Il pourrait y avoir un moyen de créer un index basé sur une fonction qui applique cette règle afin que vous puissiez vous débarrasser complètement du déclencheur. J'ai trouvé une façon, mais cela nécessite quelques hypothèses :

  • La table a une clé primaire numérique
  • La clé primaire et le t1_prnt_t1_pk sont tous deux des nombres toujours positifs

Si ces hypothèses sont vraies, vous pouvez créer une fonction comme celle-ci :

dev> create or replace function f( a number, b number ) return number deterministic as
  2  begin
  3    if a is null then return 0-b; else return a; end if;
  4  end;

et un index comme celui-ci :

CREATE UNIQUE INDEX my_index ON my_table
  ( t1_appnt_event, f( t1_prnt_t1_pk, primary_key_column) );

Ainsi, les lignes où la colonne PMNT est NULL apparaîtraient dans l'index avec l'inverse de la clé primaire comme deuxième valeur, de sorte qu'elles ne seraient jamais en conflit les unes avec les autres. Les lignes où ce n'est pas NULL utiliseraient la valeur réelle (positive) de la colonne. La seule façon d'obtenir une violation de contrainte serait si deux lignes avaient les mêmes valeurs non NULL dans les deux colonnes.

C'est peut-être trop "intelligent", mais cela pourrait vous aider à contourner votre problème.

Mise à jour de Paul Tomblin :je suis allé avec la mise à jour de l'idée originale qu'igor a mise dans les commentaires :

 CREATE UNIQUE INDEX cappec_ccip_uniq_idx 
 ON tbl1 (t1_appnt_event, 
    CASE WHEN t1_prnt_t1_pk IS NOT NULL THEN 1 ELSE t1_pk END);