Oracle
 sql >> Baza danych >  >> RDS >> Oracle

ORA-04091:tabela [blah] mutuje, wyzwalacz/funkcja może jej nie widzieć

Myślę, że nie zgadzam się z twoim opisem tego, co próbuje zrobić wyzwalacz. Wygląda na to, że ma na celu wymuszenie następującej reguły biznesowej:dla podanej wartości t1_appnt_event, tylko jeden wiersz może mieć jednocześnie wartość inną niż NULL oft1_prnt_t1_pk. (Nie ma znaczenia, czy mają tę samą wartość w drugiej kolumnie, czy nie.)

Co ciekawe, jest ona zdefiniowana dla UPDATE OF t1_appnt_event, ale nie dla drugiej kolumny, więc myślę, że ktoś mógłby złamać regułę, aktualizując drugą kolumnę, chyba że istnieje osobny wyzwalacz dla tej kolumny.

Może istnieć sposób na utworzenie indeksu opartego na funkcjach, który wymusza tę regułę, dzięki czemu można całkowicie pozbyć się wyzwalacza. Wymyśliłem jeden sposób, ale wymaga to pewnych założeń:

  • Tabela ma numeryczny klucz podstawowy
  • Klucz podstawowy i t1_prnt_t1_pk są zawsze liczbami dodatnimi

Jeśli te założenia są prawdziwe, możesz utworzyć taką funkcję:

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;

i indeks podobny do tego:

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

Tak więc wiersze, w których kolumna PMNT ma wartość NULL, pojawią się w indeksie z odwrotnością klucza podstawowego jako drugą wartością, więc nigdy nie będą ze sobą kolidować. Wiersze, w których nie ma wartości NULL, używają rzeczywistej (dodatniej) wartości kolumny. Jedynym sposobem, w jaki można uzyskać naruszenie ograniczenia, byłoby to, gdyby dwa wiersze miały te same wartości inne niż NULL w obu kolumnach.

Jest to być może zbyt „sprytne”, ale może pomóc w rozwiązaniu problemu.

Aktualizacja od Paula Tomblina:Poszedłem z aktualizacją do pierwotnego pomysłu, który Igor umieścił w komentarzach:

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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SPRAWDŹ OGRANICZENIE ciągu, aby zawierał tylko cyfry. (Oracle SQL)

  2. Jak używać wykonania natychmiastowego z klauzulą ​​INTO w bazie danych Oracle

  3. Scalanie dwóch wierszy w jeden podczas zastępowania wartości null

  4. Jak mogę nadać alias tabeli w Oracle?

  5. Zarządzany sterownik ODP.NET nie wyświetla się w oknie dialogowym Źródło danych