Oracle After Delete Trigger ... ¿Cómo evitar la tabla de mutaciones (ORA-04091)?
Digamos que tenemos las siguientes estructuras de tabla:
documents docmentStatusHistory status
+---------+ +--------------------+ +----------+
| docId | | docStatusHistoryId | | statusId |
+---------+ +--------------------+ +----------+
| ... | | docId | | ... |
+---------+ | statusId | +----------+
| ... |
+--------------------+
uede ser obvio, pero vale la pena mencionar que el estado actual de un documento es el último Historial de estado ingresado.
El sistema fue lento pero seguro degradando el rendimiento y sugerí cambiar la estructura anterior a:
documents docmentStatusHistory status
+--------------+ +--------------------+ +----------+
| docId | | docStatusHistoryId | | statusId |
+--------------+ +--------------------+ +----------+
| currStatusId | | docId | | ... |
| ... | | statusId | +----------+
+--------------+ | ... |
+--------------------+
e esta manera, tendríamos el estado actual de un documento justo donde debería estar.
ebido a la forma en que se crearon las aplicaciones heredadas, no pude cambiar el código de las aplicaciones heredadas para actualizar el estado actual en la tabla de documentos.
n este caso, tuve que abrir una excepción a mi regla para evitar los desencadenantes a toda costa, simplemente porque no tengo acceso al código de las aplicaciones heredadas.
Creé un activador que actualiza el estado actual de un documento cada vez que se agrega un nuevo estado al historial de estado, y funciona de maravilla.
in embargo, en una situación oscura y poco utilizada, es necesarioBORRA el último historial de estado, en lugar de simplemente agregar uno nuevo. Entonces, creé el siguiente disparador:
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;
Y ahí es donde obtuve el infame errorORA-04091
.
EntiendoPOR QU Recibo este error, aunque configuré el activador comoDESPUÉ disparador.
Lo que pasa es que no puedo evitar este error. He buscado en la red por un tiempo y no he podido encontrar nada útil hasta ahora.
A tiempo, estamos usando Oracle 9i.