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 Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 02-06-2008
santiaguinillo santiaguinillo is offline
Miembro
 
Registrado: abr 2007
Ubicación: Viladecans, Barcelona
Posts: 24
Poder: 0
santiaguinillo Va por buen camino
Question Continuar Procedure a pesar del salto de excepción

Hola a tod@s,

tengo un problema con un procedure.
BBDD: firebird 1.5

El procedure realiza una serie de inserts según unas condiciones. En el último insert de este procedure y que inserta en una determinada tabla X, salta una excepción. Pusimos una excepción en un trigger before insert que si no se cumple otra condición no se realice el insert en la tabla X i salte esta excepción para capturarla y mostrarla por pantalla en la aplicación delphi.

El problema viene que al saltar la excepción en esta última tabla X, el resto de inserts anteriores no se guardan. Hace rollback cuando salta la excepción.

Quisiera saber si existe la posibilidad de que aunque salte la excepción del procedure firebird, continúe con el procedure y haga finalmente commit del mismo.

Un saludo y gracias por adelantado.
Responder Con Cita
  #2  
Antiguo 02-06-2008
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.732
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
A pesar de que lo mejor sería verificar si se va a dar la excepción y actuar en consecuencia, existe una posibilidad:

WHEN XXX DO

Código SQL [-]
create procedure insertar_aglo (VALOR varchar(3))
as
begin
  for select familia from art_familias
    where(empresa=1) into :familia do
    begin
      insert into propaga(familia)
        values(:familia) ;
        when SQLCODE -803 do exit ;
    end 
end

Código SQL [-]
create procedure trunca100 (CADENA1 varchar(200))
returns (CADENA2 varchar(100))
as
begin
  /* Este procedimiento trunca la cadena a 100 caracteres */
  cadena2 ='INICIALIZA';
  cadena2 = cadena1;
  when any do suspend;
end
Responder Con Cita
  #3  
Antiguo 02-06-2008
santiaguinillo santiaguinillo is offline
Miembro
 
Registrado: abr 2007
Ubicación: Viladecans, Barcelona
Posts: 24
Poder: 0
santiaguinillo Va por buen camino
Question Continuar Procedure a pesar del salto de excepción

Hola duilioisola,

he probado de poner el código que me comentas. En concreto he probado en mi procedure:
  • when SQLCODE -803 do exit ;
  • when EXCEPTION SUPERA_IMPORTE DO exit;
(SUPERA_IMPORTE es el nombre de la excepción que salta)

Ambas opciones han salido con rollback del procedure
así que todavía no me queda resuelto el problema.

No sé como hacer para que aun saltando una excepción en un insert, el resto de inserts ejecutados anteriormente hagan commit.

Última edición por santiaguinillo fecha: 02-06-2008 a las 15:43:08. Razón: poner título
Responder Con Cita
  #4  
Antiguo 02-06-2008
Avatar de RolphyReyes
RolphyReyes RolphyReyes is offline
Miembro
 
Registrado: ago 2004
Ubicación: Santo Domingo
Posts: 285
Poder: 20
RolphyReyes Va por buen camino
Lightbulb

Saludos.

Puedes ir haciendo commit por cada inserción es inefectivo pero es una solución.

También puedes poner el código que tienes y cuando salte la excepción "forza" el commit.
__________________
Gracias,
Rolphy Reyes
Responder Con Cita
  #5  
Antiguo 02-06-2008
santiaguinillo santiaguinillo is offline
Miembro
 
Registrado: abr 2007
Ubicación: Viladecans, Barcelona
Posts: 24
Poder: 0
santiaguinillo Va por buen camino
Hacer commit

Hola RolphyReyes,

el problema es que al poner commit en el procedure me da error al compilar. Es decir, no puedo poner commit dentro del procedure.


Cita:
Empezado por RolphyReyes Ver Mensaje
Saludos.

Puedes ir haciendo commit por cada inserción es inefectivo pero es una solución.

También puedes poner el código que tienes y cuando salte la excepción "forza" el commit.
Responder Con Cita
  #6  
Antiguo 02-06-2008
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.732
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
Prueba con
* when SQLCODE -803 do SUSPEND ;
* when EXCEPTION SUPERA_IMPORTE DO SUSPEND ;

Cada vez que un procedimiento encuentra un suspend, devuelve los valores que tenga en el RETURNS() y espera a que le pidan el siguiente.

Aunque no devuelvas nada, el SUSPEND hará que devuelva el control a tu programa y puedas hacer un commit o rollback, según te convenga.
Responder Con Cita
  #7  
Antiguo 02-06-2008
santiaguinillo santiaguinillo is offline
Miembro
 
Registrado: abr 2007
Ubicación: Viladecans, Barcelona
Posts: 24
Poder: 0
santiaguinillo Va por buen camino
Question Pruebas con do suspend KO

Hola duilioisola,

¿pero el commit o rollback quieres decir que lo ponga en el código delphi? Porque he hecho lo siguiente y sigue sin hacerme commit (en el procedure he puesto when EXCEPTION SUPERA_IMPORTE DO SUSPEND):

Código Delphi [-]
      sentencia := 'EXECUTE PROCEDURE PROCESA_VISITA (variables)';
      try
        Q1.Close;
        Q1.SQL.Clear;
        Q1.SQL.Add(sentencia);
        Q1.Prepare;
        Q1.ExecQuery;   //AQUI DA LA EXCEPCIÓN
        Q1.Transaction.CommitRetaining;
        Q1.FreeHandle;
      except
        Q1.Transaction.CommitRetaining; //ESTO LO HE PUESTO AHORA Y NO HACE COMMIT
        Q1.FreeHandle;
        raise;
      end;



Cita:
Empezado por duilioisola Ver Mensaje
Prueba con
* when SQLCODE -803 do SUSPEND ;
* when EXCEPTION SUPERA_IMPORTE DO SUSPEND ;

Cada vez que un procedimiento encuentra un suspend, devuelve los valores que tenga en el RETURNS() y espera a que le pidan el siguiente.

Aunque no devuelvas nada, el SUSPEND hará que devuelva el control a tu programa y puedas hacer un commit o rollback, según te convenga.

Última edición por santiaguinillo fecha: 02-06-2008 a las 17:14:19.
Responder Con Cita
  #8  
Antiguo 02-06-2008
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.732
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
Supongo que si no sigue es porque la excepción que salta no es la que esperas en el WHEN EXCEPCION DO...
Prueba a poner WHEN ANY DO...

O prueba a ver cuál es la excepción que llega con un ShowMessage.
Código Delphi [-]
sentencia := 'EXECUTE PROCEDURE PROCESA_VISITA (variables)';
      try
        Q1.Close;
        Q1.SQL.Clear;
        Q1.SQL.Add(sentencia);
        Q1.Prepare;
        Q1.ExecQuery;   //AQUI DA LA EXCEPCIÓN
        Q1.Transaction.CommitRetaining;
        Q1.FreeHandle;
      except
         on e:exception do 
         begin
            Showmessage(e.message); //Esto te mostrará el texto de la excepcion
           Q1.Transaction.Rollback;
           Q1.FreeHandle;
           raise;
         end;
      end;

Por más que le digas que haga un commit, si ha saltado una excepción no grabará los datos.
Si quieres envíanos el código de tu procedimiento, para que le hechemos una mirada.
Pero como dije anteriormente, quizás sea mejor filtrar los casos para los que se dá la excepción.
Responder Con Cita
  #9  
Antiguo 02-06-2008
lbuelvas lbuelvas is offline
Miembro
 
Registrado: may 2003
Ubicación: Colombia
Posts: 377
Poder: 21
lbuelvas Va por buen camino
Un procedimento almacenado funciona como una unidad en donde todas las operaciones son grabadas (commit) si y solamente si no se presenta alguna violacion de integridad (llaves foraneas, primarias, campos nulos, etc). Al presentarse alguna violacion los datos de la base de datos quedan en el estado en que se encontraban justo antes de lanzar el procedimiento almacenado.

Realmente y en lo personal evito que queden datos pendientes por actualizar cuando se lanza un procedimiento almacenado, sin embargo, puedes colocar una sentencia de codigo y que te escriba en otra tabla, no que te lance una expecion porque las excepciones provocan que pierdas las actualzaciones alcanzadas hasta ese punto.

Código SQL [-]
          when any do
          begin
            INSERT INTO TS_TRAZO
            (DESCRIPCION)
            VALUES
            (texto con la observacion);
          END
        end

La tabla TS_TRAZO la puedes consultar despues para saber que paso.
__________________
Luis Fernando Buelvas T.
Responder Con Cita
  #10  
Antiguo 03-06-2008
santiaguinillo santiaguinillo is offline
Miembro
 
Registrado: abr 2007
Ubicación: Viladecans, Barcelona
Posts: 24
Poder: 0
santiaguinillo Va por buen camino
Red face Medio solucionado

Hola a todos,

pues resulta que no cogía la excepción correcta. Con el WHEN ANY DO SUSPEND; me ha funcionado correctamente y ha hecho commit de los inserts anteriores.

El "problema" es que ahora se traga la excepción y no muestra el mensaje de error ya que el código delphi no detecta excepción.

Una pregunta, ¿el insert devuelve alguna variable si se ha insertado correctamente (en el procedure)?
Si fuese así, podría devolver en el procedure una variable que diga si se ha insertado bien el último insert que es el único que provoca la excepción.
Responder Con Cita
  #11  
Antiguo 03-06-2008
Avatar de RolphyReyes
RolphyReyes RolphyReyes is offline
Miembro
 
Registrado: ago 2004
Ubicación: Santo Domingo
Posts: 285
Poder: 20
RolphyReyes Va por buen camino
Smile

Saludos.

En Firebird 2.xx tienes la clausula RETURNING pero tienes la v1.5.

No se cual es tu caso pero analiza si puedes migrar a la nueva versión que tiene más mejoras y estabilidad.

Hasta luego.
__________________
Gracias,
Rolphy Reyes
Responder Con Cita
  #12  
Antiguo 03-06-2008
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.732
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
Si quitas la sentencia WHEN ANY DO SUSPEND de tu procedimiento, la parte donde tratas las excepciones te dirá cuál es la excepción que se ha generado.

Código Delphi [-]
   except
      on e:exception do 
      begin
         Showmessage(e.message); //Esto te mostrará el texto de la excepcion
         Q1.Transaction.Rollback;
         Q1.FreeHandle;
         raise;
      end;
   end;

De todos modos, la filosofía de las excepciones es diferente a lo que parece que haces tu:
- Las excepciones hay que tratar de no utilizarlas.
- Consumen muchos recursos.
- Si salta una excepción hay que volver atrás todo lo que se ha hecho hasta entonces.
- Normalmente se puede evitar la excepción.

Por ejemplo:
Si tienes un procedimiento que divide dos valores, tienes dos opciones:
  • Verificas con un if si el divisor es distinto de 0 antes de realizar la división y si es 0 muestras un mensaje de error.
  • Realizas la división. Si salta la excepción la capturas y muestras un mensaje de error.

Supongo que lo mejor en tu caso (creo que estás insertando registros) es verificar si existe y sobrepasa un valor dado.

Código SQL [-]
   /* Sumo importe */
   select sum(importe) from tabla where condiciones
   into :importe;

   /* Verifico que no me paso del valor maximo */
   if (importe<=VALOR_MAXIMO) then
   begin
      /* Verifico que no exista para poder insertarlo */
      if (not exists(select importe from tabla where condiciones)) then
          insert into tabla (campos) values (valores);  
 
      else
         /* Si existe lo meto en tabla de errores que mostraré al usuario */
         insert into tabla_errores (detalles) values ('YA EXISTE EL VALOR A INSERTAR');
   end
   else
        /* Si sobrepasa el importe maximo lo meto en tabla de errores que mostraré al usuario */
       insert into tabla_errores (detalles) values ('SE SUPERA EL IMPORTE');

Última edición por duilioisola fecha: 03-06-2008 a las 14:56:51.
Responder Con Cita
  #13  
Antiguo 03-06-2008
santiaguinillo santiaguinillo is offline
Miembro
 
Registrado: abr 2007
Ubicación: Viladecans, Barcelona
Posts: 24
Poder: 0
santiaguinillo Va por buen camino
Wink Resuelto

Gracias a todos por vuestras respuestas.

Doy el problema por resuelto. Finalmente con el when any do suspend; ha sido suficiente y aunque ya no muestra el mensaje de la excepción no es realmente grave.

Seria interesante haber tenido lo que comentaba RolphyReyes sobre Returning y de esta forma podría haber devuelto alguna variable para informar de que no se ha introducido el último registro.

Es para esto que teníamos las excepciones, para informar de ello a la aplicación delphi. Lo que no queríamos es que nos hiciera rollback de las anteriores operaciones en la bbdd del procedimiento.

En mi caso no podría hacerlo de otra forma, ni de la forma que comenta duilioisola en el código sql ya que el último insert del procedure se efectua o no dependiendo de unas condiciones que hay en el trigger before insert de la tabla que intenta insertar. Por lo tanto, o bien ponemos el código del trigger en el mismo procedure o bien necesitaríamos el returning que ya tiene el firebird 2.0

De nuevo, gracias a todos por vuestro aporte.
Santi.
Responder Con Cita
  #14  
Antiguo 11-06-2008
Avatar de rastafarey
rastafarey rastafarey is offline
Miembro
 
Registrado: nov 2003
Posts: 927
Poder: 21
rastafarey Va por buen camino
Resp

Dentro de un disparador no vas a poder decir que no inserte o que no haga lo que uba ahacer en su tabla. Por exactamente la accion de insertar es la que dispara el disparador. Lo que si puedes hacer desde el disparador verifcar al condicion que te hace saltar la exception antes de manadar a insertar.
__________________
Todo se puede, que no exista la tecnología aun, es otra cosa.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

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
continuar una numeracion con Qreport Alfredo Impresión 7 23-10-2007 12:05:53
Key violation. Continuar con siguiente registro CHiCoLiTa Conexión con bases de datos 11 14-02-2007 22:48:37
Continuar numeracion en impresion !! Help RJF Impresión 2 07-11-2006 05:43:17
Desea continuar? SI NO CANCELAR (3 Botones en el formulario) dmassive PHP 3 26-08-2005 20:22:08
No se continuar pepelu1975 Varios 1 19-02-2004 12:02:22


La franja horaria es GMT +2. Ahora son las 08:56:55.


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