Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

ORA-04091:a tabela [blah] está mudando, o gatilho/função pode não ver


Acho que discordo da sua descrição do que o gatilho está tentando fazer. Parece-me que se destina a impor esta regra de negócios:para um determinado valor de t1_appnt_event, apenas uma linha pode ter um valor não NULL oft1_prnt_t1_pk por vez. (Não importa se eles têm o mesmo valor na segunda coluna ou não.)

Curiosamente, ele é definido para UPDATE OF t1_appnt_event, mas não para a outra coluna, então acho que alguém poderia quebrar a regra atualizando a segunda coluna, a menos que haja um gatilho separado para essa coluna.

Pode haver uma maneira de criar um índice baseado em função que imponha essa regra para que você possa se livrar completamente do gatilho. Eu vim com uma maneira, mas requer algumas suposições:
  • A tabela tem uma chave primária numérica
  • A chave primária e o t1_prnt_t1_pk são sempre números positivos

Se essas suposições forem verdadeiras, você pode criar uma função como esta:
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 um índice como este:
CREATE UNIQUE INDEX my_index ON my_table
  ( t1_appnt_event, f( t1_prnt_t1_pk, primary_key_column) );

Portanto, as linhas em que a coluna PMNT é NULL apareceriam no índice com o inverso da chave primária como o segundo valor, de modo que nunca entrariam em conflito entre si. As linhas em que não é NULL usariam o valor real (positivo) da coluna. A única maneira de obter uma violação de restrição seria se duas linhas tivessem os mesmos valores não NULL em ambas as colunas.

Isso talvez seja excessivamente "inteligente", mas pode ajudá-lo a contornar seu problema.

Atualização de Paul Tomblin:Fui com a atualização da ideia original que igor colocou nos comentários:
 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);