Oracle
 sql >> Database >  >> RDS >> Oracle

ORA-04091:la tabella [blah] sta mutando, il trigger/la funzione potrebbe non vederlo

Penso di non essere d'accordo con la tua descrizione di ciò che il trigger sta cercando di fare. Mi sembra che abbia lo scopo di applicare questa regola aziendale:per un determinato valore di t1_appnt_event, solo una riga può avere un valore non NULL oft1_prnt_t1_pk alla volta. (Non importa se hanno lo stesso valore nella seconda colonna o meno.)

È interessante notare che è definito per UPDATE OF t1_appnt_event ma non per l'altra colonna, quindi penso che qualcuno potrebbe infrangere la regola aggiornando la seconda colonna, a meno che non ci sia un trigger separato per quella colonna.

Potrebbe esserci un modo per creare un indice basato su funzioni che applica questa regola in modo da poter eliminare completamente il trigger. Mi è venuto in mente un modo ma richiede alcune ipotesi:

  • La tabella ha una chiave primaria numerica
  • La chiave primaria e t1_prnt_t1_pk sono entrambi sempre numeri positivi

Se queste ipotesi sono vere, potresti creare una funzione come questa:

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;

e un indice come questo:

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

Quindi le righe in cui la colonna PMNT è NULL apparirebbero nell'indice con l'inverso della chiave primaria come secondo valore, quindi non sarebbero mai in conflitto tra loro. Le righe in cui non è NULL utilizzeranno il valore effettivo (positivo) della colonna. L'unico modo per ottenere una violazione del vincolo sarebbe se due righe avessero gli stessi valori non NULL in entrambe le colonne.

Questo è forse eccessivamente "intelligente", ma potrebbe aiutarti a aggirare il tuo problema.

Aggiornamento da Paul Tomblin:sono andato con l'aggiornamento all'idea originale che igor ha inserito nei commenti:

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