Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   Un trigger que dispara un procedimiento que dispara un trigger... (https://www.clubdelphi.com/foros/showthread.php?t=43863)

sitrico 22-05-2007 22:58:59

Un trigger que dispara un procedimiento que dispara un trigger...
 
Más que una pregunta es una duda. (es mi primera vez :D ) a ver:

Quiero manejar 2 tablas donde la inserción en la primera (co_detalleconsultas) causa la inserción en la segunda (ad_serviciosasignados) por medio de un procedimiento almacenado que genera el idservasig que al final del procedimiento se guarda en la 1ra tabla con un update.

¿ Este enfoque es viable y recomendable o mejor busco otra solución ?

--- el código ---

En un trigger after insert en co_detalleconsultas lanzo:

Código SQL [-]
execute procedure ad_asignarserviciosprestados(new.idpaciente, New.idservicio);

que llama al procedimiento

Código SQL [-]
CREATE PROCEDURE AD_ASIGNARSERVICIOSPRESTADOS (
    aidpaciente integer,
    aidservicio integer)
as
declare variable sidservasig integer;
declare variable didservicio integer;
declare variable cidpaciente integer;
declare variable diddetcons integer;
declare variable scantidadsesiones integer;
declare variable ssecionesrealizadas integer;
declare variable lsesiones integer;
begin
  FOR
  Select  d.IDDETCONS, s.idservasig, d.IdServicio, d.IdPaciente, s.cantidadsesiones, s.secionesrealizadas, l.sesiones
  from co_detalleconsultas d
  left join ad_serviciosasignados S
  on d.idpaciente = s.idpaciente And d.idservicio = S.idservicio And
    (s.cantidadsesiones is null or s.cantidadsesiones > s.secionesrealizadas)
  join dg_listaservicios L On d.idservicio = l.idservicio
  Where d.IdPaciente = :aIdPaciente and d.IdServicio = :aidservicio
  -- variables para los resultados
  into :diddetcons, :sidservasig, :dIdServicio, :cIdPaciente, :scantidadsesiones, :ssecionesrealizadas, :lsesiones
     DO
     BEGIN
     if (sidservasig is null) then
        Begin
        -- aqui se determina el nuevo ID usando un generador
        sidservasig = GEN_ID(GEN_AD_SERVICIOSASIGNADOS_ID,1);
        Insert into ad_serviciosasignados
           (idservasig, idservicio, idpaciente, iddetcons, cantidadsesiones, secionesrealizadas, fchinicio, fchfinal) values
           (:sidservasig, :dIdServicio, :cIdPaciente, :diddetcons, :lsesiones, 1, current_date, current_date);
        End
     Else
        Begin
        Update ad_serviciosasignados Set
            secionesrealizadas = :ssecionesrealizadas +1,
            fchfinal = current_date
        Where idservasig = :sidservasig;
        End
     Update co_detalleconsultas SET
        IDSERVASIG = :sidservasig
     Where co_detalleconsultas.iddetcons = :diddetcons;
     suspend;
     End
end

Que según (YO) cada vez que hay una consulta (de estetica) asigna la consulta (para efectos la pone en cuentas por cobrar - ad_serviciosasignados) y si se trata de un paquete (varias consultas = 1 asignación) aumenta el contador:

secionesrealizadas = :ssecionesrealizadas +1

Al final ejecuta el código:

Código SQL [-]
     Update co_detalleconsultas SET
        IDSERVASIG = :sidservasig
     Where co_detalleconsultas.iddetcons = :diddetcons;

Que "Regresa" el sidservasig a al detalle de la consulta (para saber a que control se asignó)

rastafarey 01-06-2007 20:02:09

Resp
 
No voy a leer todo el codigo.

Pero si quieres usar recursion no se puede.

Lepe 01-06-2007 20:15:33

Que en un trigger after insert ejecute un SP para agregar un registro a otra tabla, lo veo correcto.

Que ese SP modifique la primera tabla, eso ya no me parece lógico. Quizás deberías usar un trigger before Insert, así modificas campos en la primera tabla, y además lanzas la inserción en la segunda.

El SP se supone está compilado... pero no me queda claro eso de hacer 2 inner joins cuando se va a ejecutar en un trigger, quizás fuera mejor usar una vista.
Para este detalle me gustaría que otros foristas opinaran.

Si ya tienes un trigger before insert de la primera tabla y no quieres modificarlo, siempre puedes usar el "position 1"

Saludos

sitrico 02-06-2007 00:33:55

Gracias por las respuestas :)

Primero debo aclarar que aunque parezca raro: ¡ funciona ! (yo mismo no lo creia)

rastafarey: no es recursión

La idea -simplificada- es: La primera tabla recibe los datos del cliente, luego de insertarlos (after insert) el servidor llama al procedimiento que pasa los datos correspondientes a otra tabla (en este proceso se genera el Nº de ID) y luego se envia (update) el Nº de ID a la primera tabla.

Lepe: La idea de usar el before insert me parece interesante, pero considerando el caso: (la primera tabla guarda el servicio prestado y luego de "prestado el servicio" se llama al SP para que cree la cuenta por pagar) supongo que el resultado final sería el mismo, pero prefiero almacenar primero el servicio y luego crear la deuda.

debo aclarar que no domino mucho la programación del lado del servidor en firebird (es mi 1ra applicación) así que el tema de las vistas ó usar el "position 1" escapan de mis conocimientos ...por ahora :cool:

Lepe 02-06-2007 09:48:29

Todod el proceso se realiza en una transacción, por tanto, si una de las dos cosas falla, se deshace el proceso completo. Por eso no importa crear primero la deuda que el servicio, aunque como dices, parece lógico hacerlo al revés.

El "position 1" es un parámetro al tiempo de crear varios triggers after insert para una misma tabla, con ese parámetro indicas en qué orden deben ejecutarse esos triggers (no sé si tienes ya un trigger before insert o no).

La vista, échale una ojeada ya mismo. Seguro que tendrás que hacer varios inner joins cuando quieres acceder a las tablas, con la vista, te evitas hacerlos.

Código SQL [-]
Create View vwClientes( 
idcliente,
nombre,
servicio prestado, 
idservicio)

as

select c.idcliente, c.nombre, s.Servicio prestado, s.idservicio
from clientes c inner join servicios s on c.idcliente = s.idcliente

end.
Ya puedes acceder a esta vista como si fuera una tabla más, con la peculiaridad de reunir información de varias tablas al mismo tiempo.

Saludos

sitrico 04-06-2007 22:05:13

Gracias lepe, no conocía las vistas, por lo que te entendí trabajan como una suerte de tabla "virtual", almacenando un select (complejo) para devolver los datos solicitados :cool:

Bueno a leer un rato...


La franja horaria es GMT +2. Ahora son las 00:30:00.

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