Oracle Após excluir o gatilho… Como evitar a tabela de mutação (ORA-04091)?
Digamos que temos as seguintes estruturas de tabela:
documents docmentStatusHistory status
+---------+ +--------------------+ +----------+
| docId | | docStatusHistoryId | | statusId |
+---------+ +--------------------+ +----------+
| ... | | docId | | ... |
+---------+ | statusId | +----------+
| ... |
+--------------------+
Pode ser óbvio, mas vale a pena mencionar, que o status atual de um documento é o último histórico de status inserid
O sistema estava lenta mas seguramente degradando o desempenho e sugeri alterar a estrutura acima para:
documents docmentStatusHistory status
+--------------+ +--------------------+ +----------+
| docId | | docStatusHistoryId | | statusId |
+--------------+ +--------------------+ +----------+
| currStatusId | | docId | | ... |
| ... | | statusId | +----------+
+--------------+ | ... |
+--------------------+
Dessa forma, teríamos o status atual de um documento exatamente onde deveria esta
Como a maneira como os aplicativos herdados foram criados, não pude alterar o código nos aplicativos herdados para atualizar o status atual na tabela de documento
Nesse caso, tive que abrir uma exceção à minha regra para evitar gatilhos a todo custo, simplesmente porque não tenho acesso ao código de aplicativos herdado
Criei um gatilho que atualiza o status atual de um documento toda vez que um novo status é adicionado ao histórico de status e funciona como um encant
No entanto, em uma situação obscura e raramente usada, é necessárioEXCLUI o último histórico de status, em vez de simplesmente adicionar um novo. Então, eu criei o seguinte gatilho:
create or replace trigger trgD_History
after delete on documentStatusHistory
for each row
currentStatusId number;
begin
select statusId
into currentStatusId
from documentStatusHistory
where docStatusHistoryId = (select max(docStatusHistoryId)
from documentStatusHistory
where docId = :old.docId);
update documentos
set currStatusId = currentStatusId
where docId = :old.docId;
end;
E foi aí que eu recebi o erro infameORA-04091
.
CompreendoPORQU Estou recebendo esse erro, embora tenha configurado o gatilho comoDEPOIS D desencadear
O problema é que não consigo ver uma maneira de contornar esse erro. Pesquisei na net por um tempo e até agora não consegui encontrar nada útil.
om o tempo, estamos usando o Oracle 9