Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Firebird e Interbase
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 03-11-2006
sur-se sur-se is offline
Miembro
 
Registrado: may 2003
Posts: 212
Poder: 21
sur-se Va por buen camino
Disparo de triggers en Firebird

Hola. Me está ocurriendo un problema bastante extraño con el disparo de los triggers y el borrado en cascada. Para resumir pondré la situación a modo de ejemplo:

- Tabla cabecera: número (primary key), campo1,campo2, campo3 ...
- Tabla de líneas: número (referencia a la tabla anterior, on delete cascade), orden, lcampo1, lcampo2, ...
primary key (número, orden)

La situación es tal que si borro la cabecera, por el "on delete cascade" se me borran las líneas. Esto es correcto. Sigamos...

En la tabla de líneas tengo un trigger after delete que opera de la forma siguiente:

- Lee de la cabecera el campo3 (por ejemplo) y si tiene un valor determinado ejecuta un operación de actualización.

Es decir, si borro una línea, se dispara el trigger y lee un campo de la cabecera que determina si debe efectuarse o no una operación (en mi caso actualizar las existencias).
Esto funciona bien, es decir si borro las líneas se van efectuando las operaciones de actualización.
El problema está cuando quiero borrarlo todo. En este caso borro la cabecera, y el "on delete cascade" me borra las líneas. Y aquí viene el problema. Da la impresión de que primero borra la cabecera y luego las líneas por lo que el trigger de las líneas no lee bien el valor del campo de la cabecera y no efectua correctamente la actualización cuando corresponde.

Lo lógico sería que si hay registros que apuntan a mi tabla principal (cabecera), primero se borraran las líneas (por el on delete cascade) y luego la cabecera. Pero parece que no lo hace así y el trigger no va bien.

¿Es esto lógico que funcione así?. La solución por la que he optado es lanzar primero un borrado de las líneas y luego de la cabecera, pero entonces, para que me he molestado en poner el "on delete cascade" si después no lo puedo utilizar.
Salu2.
Responder Con Cita
  #2  
Antiguo 03-11-2006
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
... y digo yo.

Por qué no utilizas precisamente un Trigger que sea 'BEFORE DELETE' con lo cual tu registro en la cabecera seguirá existiendo.
__________________
Piensa siempre en positivo !
Responder Con Cita
  #3  
Antiguo 03-11-2006
sur-se sur-se is offline
Miembro
 
Registrado: may 2003
Posts: 212
Poder: 21
sur-se Va por buen camino
Muy sencillo, porque da igual que sea before o after, porque el problema es que el trigger está en la línea no en la cabecera. Así que da un poco igual que sea antes de borrar línea o después de borrarla.
El problema es que desde el trigger de la línea se debe leer un campo de la cabecera.
Salu2.
Responder Con Cita
  #4  
Antiguo 03-11-2006
tefots tefots is offline
Miembro
 
Registrado: feb 2005
Posts: 108
Poder: 20
tefots Va por buen camino
el problema está que en la tabla de lineas , tienes una referencia a la tabla cabecera y el 'ondelete cascade' como regla en la clave ajena.
este 'ondelete cascade' se ejecuta por defecto cuando has borrado el registro (after delete) , con lo que cuando se borra algun registro de la cabecera y desde un triger en en el delete de las lineas intentas acceder a la cabecera , esta ya no existe.

la solucion está en modificar este trigger de la tabla lineas (aunque realmente se ejecutacuando en el after delete de la cabecera) que genera firebird automáticamente y pasarlo de 'after delete' , a 'before delete' .

esto lo puedes hacer con ibexpert, entras en las dependencias de la tabla lineas , y verás que en triggers , tienes alguno que se llama checkxx , ( si tienes varios has de buscar el que hace referencia al campo que enlaza con la tabla cabecera) y cambiar la regla , de after a before.


Tambien puedes hacerlo de otra forma mas facil , quitas el 'ondelete' automatico , y crear tu manualmente el trigger en la cabecera , para que en el before delete de la cabecera , elimine las lineas.

es un poco lioso , pero espero haberlo aclarado.

saludos.

Última edición por tefots fecha: 03-11-2006 a las 15:00:42.
Responder Con Cita
  #5  
Antiguo 03-11-2006
Avatar de rastafarey
rastafarey rastafarey is offline
Miembro
 
Registrado: nov 2003
Posts: 927
Poder: 21
rastafarey Va por buen camino
resp

No tengo tiempo para explicarte cual podria ser el problema pero aqui esta tu respuesta.

* Si es un trigger de tipo INSERT, entonces para acceder a los campos se debe utilizar el prefijo NEW.
* Si es un trigger de tipo UPDATE, entonces NEW nos dará el nuevo valor del campo (en caso de que haya sido modificado) y OLD nos dará el valor del campo antes de la modificación.
* Si es un trigger de tipo DELETE, se debe utilizar únicamente el prefijo OLD.
* Solamente se pueden modificar los valores de los campos en triggers de tipo BEFORE, obviamente solo BEFORE INSERT y BEFORE UPDATE.
* Se recomienda que si se van a modificar valores de otras tablas, se hagan en triggers de tipo AFTER.

Esto se encuenta en el link Mira aqui
__________________
Todo se puede, que no exista la tecnología aun, es otra cosa.
Responder Con Cita
  #6  
Antiguo 06-11-2006
sur-se sur-se is offline
Miembro
 
Registrado: may 2003
Posts: 212
Poder: 21
sur-se Va por buen camino
Hola. Gracias por la respuestas, pero ninguna entiendo que es la solución "correcta" ( desde mi punto de vista claro) , es decir, voy a tener que parchear y cambiar por algo que entiendo debería funcionar bien, que no es más que conjugar reglas de claves referenciales con triggers.

Yo entiendo que el servidor Firebird debería funcionar así en este caso:
- Quiero borrar un registro de la tabla principal. Veo si hay tablas que tengan alguna clave referencial a la tabla principal.
- Primero borro los registros (o pongo a nulo dependiendo de la configuración de las claves referenciales) de las tablas asociadas.
- Al efectuar esta operación sobre las tablas asociadas, se disparan sus triggers correspondientes.
- Una vez finalizado con las tablas asociadas, borro el registro de la tabla principal.
- Se completa la transacción.

... Pero por lo que veo, estoy equivocado .. porque parece que primero borra el registro de la tabla principal (dejando rotos los enlaces a las claves referenciales) y luego ataca a las tablas asociadas por la FK, y por eso tengo y o el problema ...

En la pregunta he simplificado bastante el proceso a dos tablas, pero la realidad es que son mas tablas las que dependen de la misma cabecera, por lo que el on-delete-cascade viene estupendamente, así como el disparo de los triggers after delete de la línea para quitar las existencias. De hecho, como comentaba en el post anterior, da igual que lo pase de after a before por que es un trigger de la línea no de la cabecera, pero tampoco lo puedo pasar al before de la línea porque se realizan sumas y acumulados con las líneas que quedan y debe realizarse cuando la línea ya está borrada y no antes.

Pero en fin, si así es como funciona pues tendré que cambiar la programación. Lo más sencillo creo que es borrar las tablas asociadas por la clave referencial con un trigger en el before delete de la cabecera, como apuntais en el post anterior.

Bueno, pues nada, eso es lo que hay. Gracias a todos por la ayuda.
Salu2.

Última edición por sur-se fecha: 06-11-2006 a las 13:56:20.
Responder Con Cita
  #7  
Antiguo 06-11-2006
Avatar de rastafarey
rastafarey rastafarey is offline
Miembro
 
Registrado: nov 2003
Posts: 927
Poder: 21
rastafarey Va por buen camino
Resp

No te entiendo. Si ya tienes creada la integridad referencial para que tienes que borrar a mano. Para eso creaste la integridad referencial. Eso se activa solo.

Bueno eso es lo que estoy entiendo segun lo que me dices.
__________________
Todo se puede, que no exista la tecnología aun, es otra cosa.
Responder Con Cita
  #8  
Antiguo 07-11-2006
sur-se sur-se is offline
Miembro
 
Registrado: may 2003
Posts: 212
Poder: 21
sur-se Va por buen camino
Hola. Lee el post del principio. Es un problema con los triggers de la tabla de líneas, y la integridad referencial no la puedo utilizar para el borrado en cascada.
Salu2.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Ocultar código de Stored Procedures y Triggers en FireBird... jncrls Firebird e Interbase 4 08-01-2007 16:51:52
efecto disparo de los juegos edusus Varios 15 19-04-2006 03:10:12
Firebird 1.0.3 -- Recusividad de Triggers y Procedimientos Almacenados jverasobino Firebird e Interbase 1 27-12-2004 18:00:58
Problemas Triggers Firebird ISCOPYME Firebird e Interbase 2 29-06-2004 22:05:12
[Firebird 1.5] DSQL en procedimientos almacenados y triggers kinobi Firebird e Interbase 0 06-08-2003 20:50:27


La franja horaria es GMT +2. Ahora son las 06:01:36.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi