Oracle
 sql >> Datenbank >  >> RDS >> Oracle

ORA-04091:Tabelle [bla] mutiert, Auslöser/Funktion sieht sie möglicherweise nicht

Ich glaube, ich bin mit Ihrer Beschreibung dessen, was der Auslöser zu tun versucht, nicht einverstanden. Es sieht für mich so aus, als ob es dazu gedacht ist, diese Geschäftsregel durchzusetzen:Für einen gegebenen Wert von t1_appnt_event kann jeweils nur eine Zeile einen Nicht-NULL-Wert von oft1_prnt_t1_pk haben. (Es spielt keine Rolle, ob sie in der zweiten Spalte denselben Wert haben oder nicht.)

Interessanterweise ist es für UPDATE OF t1_appnt_event definiert, aber nicht für die andere Spalte, also denke ich, dass jemand die Regel brechen könnte, indem er die zweite Spalte aktualisiert, es sei denn, es gibt einen separaten Auslöser für diese Spalte.

Es könnte eine Möglichkeit geben, einen funktionsbasierten Index zu erstellen, der diese Regel erzwingt, sodass Sie den Trigger vollständig beseitigen können. Ich habe mir einen Weg ausgedacht, aber es erfordert einige Annahmen:

  • Die Tabelle hat einen numerischen Primärschlüssel
  • Der Primärschlüssel und t1_prnt_t1_pk sind beide immer positive Zahlen

Wenn diese Annahmen zutreffen, könnten Sie eine Funktion wie diese erstellen:

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;

und einen Index wie diesen:

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

Zeilen, in denen die PMNT-Spalte NULL ist, würden also im Index mit der Umkehrung des Primärschlüssels als zweitem Wert erscheinen, sodass sie niemals miteinander in Konflikt geraten würden. Zeilen, in denen es nicht NULL ist, würden den tatsächlichen (positiven) Wert der Spalte verwenden. Die einzige Möglichkeit, eine Einschränkungsverletzung zu erhalten, wäre, wenn zwei Zeilen in beiden Spalten dieselben Nicht-NULL-Werte hätten.

Das ist vielleicht zu "klug", aber es könnte Ihnen helfen, Ihr Problem zu umgehen.

Update von Paul Tomblin:Ich bin mit dem Update auf die ursprüngliche Idee gegangen, die igor in den Kommentaren hinterlassen hat:

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