recursive - with update postgresql
Prevenir disparador recursivo en PostgreSQL (4)
Al principio de la definición del desencadenante, puede deshabilitar los desencadenantes en esa tabla en particular y volver a habilitarlos al final (¡y asegurarse de que una excepción no termine la ejecución antes de lo esperado!). Esto tiene muchos agujeros profundos, pero puede funcionar para algunas implementaciones ligeras. Tenga en cuenta que para esta implementación, también necesitará privilegios para deshabilitar los desencadenadores.
¿Cómo prevenir la ejecución recursiva del gatillo? Digamos que quiero construir una descripción "apta para árbol" en el cuadro de cuenta. Entonces, lo que hago es cuando se inserta / actualiza un nuevo registro, actualizo el down_qty
del registro down_qty
, por lo que esto down_qty
desencadenante de la actualización de forma recursiva.
En este momento, mi código está bien. Pongo esto en la primera línea del activador UPDATE
:
-- prevents recursive trigger
if new.track_recursive_trigger <> old.track_recursive_trigger then
return new;
end if;
Y este es el código de muestra de mi activador cuando necesito actualizar la cantidad del registro principal:
update account_category set
track_recursive_trigger = track_recursive_trigger + 1, -- i put this line to prevent recursive trigger
down_qty = down_qty - (old.down_qty + 1)
where account_category_id = m_parent_account;
Estoy pensando si hay una manera en PostgreSQL para detectar el desencadenante recursivo sin introducir un nuevo campo, algo análogo al trigger_nestlevel
de MSSQL.
[EDITAR]
Hago un bucle dentro del árbol, necesito hacer que el down_qty
de cada account_category
vuelva a su raíz. Por ejemplo, inserto una nueva categoría de cuenta, necesita down_qty
el down_qty
de su cuenta principal_categoría, al igual que cuando cambio la categoría de cuenta primaria de la account_category
, necesito disminuir el down_qty
de la account_category
principal de account_category
. Aunque creo que puede, no estoy dejando que PostgreSQL haga el desencadenante recursivo. Utilicé MSSQL antes de que el nivel de profundidad recursiva del desencadenador esté limitado solo a 16
niveles.
En pg, depende de usted realizar un seguimiento de la recursión del disparador.
Si una función de disparador ejecuta comandos SQL, estos comandos pueden disparar nuevamente los disparadores. Esto se conoce como disparadores en cascada. No hay una limitación directa en el número de niveles en cascada. Es posible que las cascadas causen una invocación recursiva del mismo activador; por ejemplo, un disparador INSERT podría ejecutar un comando que inserta una fila adicional en la misma tabla, lo que hace que el disparador INSERT se vuelva a disparar. Es responsabilidad del programador desencadenante evitar una recursión infinita en tales escenarios.
http://www.postgresql.org/docs/8.3/static/trigger-definition.html
Esto es lo que hago en PostgreSQL 9.2, aunque debo admitir que no encontré este enfoque documentado. Hay una función pg_trigger_depth()
documentada aquí , que uso para diferenciar entre llamadas originales y llamadas anidadas en el activador.
CREATE TRIGGER trg_taxonomic_positions
AFTER INSERT OR UPDATE OF taxonomic_position
ON taxon_concepts
FOR EACH ROW
WHEN (pg_trigger_depth() = 0)
EXECUTE PROCEDURE trg_taxonomic_positions()
Para evitar una recursión ilimitada, vea mi respuesta aquí . Como otros han comentado, si su estructura de datos es un verdadero árbol (la (s) raíz (s) no tendrá padre (s)) y la recursión siempre se detendrá en la (s) raíz (s). Para nodos con un solo puntero principal, la única forma de recursión ilimitada sería si hubiera bucles presentes. (El método en mi enlace visitará cualquier nodo como máximo una vez)