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)
-   -   Actualizar campo de tabla después de excepción (https://www.clubdelphi.com/foros/showthread.php?t=70045)

Axel_Tech 27-09-2010 11:58:22

Actualizar campo de tabla después de excepción
 
Hola a todos, a ver si alguien me puede dar una idea de como solucionar el siguiente problema: tengo un trigger before insert que si se cumple una determinada condición salta una excepción y también quiero que se meta en un campo del registro anterior (temporalmente hablando) un texto con el error.
Estoy probando de estas dos formas:
Código SQL [-]
begin
   IF (condicion) THEN
      BEGIN
         EXCEPTION NOMBREEXCEPCION 'Texto de la excepción.';
         UPDATE TABLA SET CAMPO1 = 'DESCRIPCIÓN DE LA EXCEPCIÓN' WHERE CAMPOCLAVE = 'DATO';  
      END
end

Código SQL [-]
begin
   IF (condicion) THEN
      BEGIN
         EXCEPTION NOMBREEXCEPCION;   
      END
      
    WHEN EXCEPTION NOMBREEXCEPCION DO
      BEGIN                             
         EXCEPTION NOMBREEXCEPCION 'Texto de la excepción.';
         UPDATE TABLA SET CAMPO1 = 'DESCRIPCIÓN DE LA EXCEPCIÓN' WHERE CAMPOCLAVE = 'DATO';
      END
end

y con las 2 me salta la excepción pero no me hace el update. ¿Automáticamente cuando hay una excepción se cancela todo lo que hace el trigger? Estoy usando Firebird 2.5

Axel_Tech 27-09-2010 12:42:45

Estoy incluso probando con un insert como lo pone en FirebirdSql.org y no funciona!!!
Código SQL [-]
when any do
begin
  insert into error_log (...) values (sqlcode, ...);
  exception;
end

guillotmarc 27-09-2010 12:43:39

Cita:

Empezado por Axel_Tech (Mensaje 377600)
Hola a todos, a ver si alguien me puede dar una idea de como solucionar el siguiente problema: tengo un trigger before insert que si se cumple una determinada condición salta una excepción y también quiero que se meta en un campo del registro anterior (temporalmente hablando) un texto con el error.
Estoy probando de estas dos formas:
Código SQL [-]begin IF (condicion) THEN BEGIN EXCEPTION NOMBREEXCEPCION 'Texto de la excepción.'; UPDATE TABLA SET CAMPO1 = 'DESCRIPCIÓN DE LA EXCEPCIÓN' WHERE CAMPOCLAVE = 'DATO'; END end


Código SQL [-]begin IF (condicion) THEN BEGIN EXCEPTION NOMBREEXCEPCION; END WHEN EXCEPTION NOMBREEXCEPCION DO BEGIN EXCEPTION NOMBREEXCEPCION 'Texto de la excepción.'; UPDATE TABLA SET CAMPO1 = 'DESCRIPCIÓN DE LA EXCEPCIÓN' WHERE CAMPOCLAVE = 'DATO'; END end


y con las 2 me salta la excepción pero no me hace el update. ¿Automáticamente cuando hay una excepción se cancela todo lo que hace el trigger? Estoy usando Firebird 2.5

Hola.

En efecto, si no estoy muy equivocado cuando haces una excepción estás cancelando la transacción y por lo tanto todos los cambios hechos en la tabla (y en el Trigger).

Si no quieres que se cancelen cambios y simplemente quieres notificar de algo a tu aplicación, en lugar de usar excepciones usa eventos (POST_EVENT).

Con un IBEvents capturarás en tu aplicación el evento que se lance en el trigger.

http://www.delphiaccess.com/forum/in...p?topic=3135.0

guillotmarc 27-09-2010 12:47:02

Ya que estás usando Firebird 2.5, puedes lanzar la inserción del error en tu Log, dentro del contexto de otra conexión a la base de datos, y por lo tanto no se verá afectado por la transacción cancelada por la excepción.

http://www.firebirdsql.org/rlsnotesh...psql-exctstmnt

Utiliza ON EXTERNAL en un EXECUTE STATEMENT.

Axel_Tech 27-09-2010 13:39:14

Gracias por contestar Guillotmarc, lo del IBEvents no lo puedo hacer porque la aplicación en cuestión está hecha en Visual Basic.NET, y lo del ON EXTERNAL lo estoy probando así:
Código SQL [-]
begin
   IF (condicion) THEN
      BEGIN
         EXECUTE STATEMENT 'UPDATE TABLA SET CAMPO1 = ''DESCRIPCIÓN DE LA EXCEPCIÓN'' WHERE CAMPOCLAVE = ''DATO'''        
         ON EXTERNAL DATA SOURCE '192.168.x.x:/RUTA/BASEDATOS.GDB' 
         AS USER 'SYSDBA' PASSWORD 'password';  

         EXCEPTION NOMBREEXCEPCION 'Texto de la excepción.'; 
      END
end

y tampoco funciona :( salta la excepción pero no me hace el update. Se ve que también lo cancela. ¿Alguna idea?

Gallosuarez 27-09-2010 17:36:30

Otra opción...
 
Es correcto lo que menciona Guillotemarc con respecto de las transacciones. Sin embargo, como estás utilizando Firebird 2.5, entonces puedes hacerlo dentro de una transacción autónoma. Aqui pongo una posible solución a tu problema...

Código SQL [-]
begin
      
    WHEN EXCEPTION NOMBREEXCEPCION DO
      BEGIN                             
         EXCEPTION NOMBREEXCEPCION 'Texto de la excepción.';
         ON AUTONOMOUS TRANSACTION DO
         BEGIN 
           UPDATE TABLA SET CAMPO1 = 'DESCRIPCIÓN DE LA EXCEPCIÓN' WHERE CAMPOCLAVE = 'DATO';
         END
      END
end

Por favor, antes de poner tal cual, este procedimiento revisa que TODA la lógica este correcta. Simplemente trato de ejemplificar que este problema se puede solucionar de esta manera.

Saludos.
Gerardo Suárez Trejo

P.D. No dejes de publicar tu código final y platicarnos como te fue... saludos nuevamente

Axel_Tech 27-09-2010 18:14:01

Justo lo que necesitaba Gallosuarez, funciona a la perfección. Es igual que como tú lo has puesto sólo que con 2 pequeñas correcciones: el ON es un IN y hay que poner la excepción después de la transacción autónoma:
Código SQL [-]
begin     
    IF (condicion) THEN
      BEGIN                             
         IN AUTONOMOUS TRANSACTION DO
            BEGIN 
              UPDATE TABLA SET CAMPO1 = 'DESCRIPCIÓN DE LA EXCEPCIÓN' WHERE CAMPOCLAVE = 'DATO';
            END
         EXCEPTION NOMBREEXCEPCION 'Texto de la excepción.';
      END
end
Tampoco hace falta meterlo en un bloque WHEN, aunque también funciona.
Que maravilla estas características nuevas en la versión 2.5... Mil gracias, salu2 ;)

guillotmarc 27-09-2010 21:04:17

Cita:

Empezado por Axel_Tech (Mensaje 377608)
Gracias por contestar Guillotmarc, lo del IBEvents no lo puedo hacer porque la aplicación en cuestión está hecha en Visual Basic.NET, y lo del ON EXTERNAL lo estoy probando así:
Código SQL [-]begin IF (condicion) THEN BEGIN EXECUTE STATEMENT 'UPDATE TABLA SET CAMPO1 = ''DESCRIPCIÓN DE LA EXCEPCIÓN'' WHERE CAMPOCLAVE = ''DATO''' ON EXTERNAL DATA SOURCE '192.168.x.x:/RUTA/BASEDATOS.GDB' AS USER 'SYSDBA' PASSWORD 'password'; EXCEPTION NOMBREEXCEPCION 'Texto de la excepción.'; END end


y tampoco funciona :( salta la excepción pero no me hace el update. Se ve que también lo cancela. ¿Alguna idea?

¿ En serio también lo cancela ?. Entonces las consultas a la base de datos externas las debe hacer forzosamente mediante la misma transacción, es decir con un two phase commit.

http://www.ibphoenix.com/main.nfs?a=...E;ID=%27217%27

Me parece espectacular, no me lo esperaba. Aunque en este caso nos estropea lo que queríamos hacer, para un uso normal es mucho mejor tenerlo todo englobado en la misma transacción.

NOTA: Por cierto, lo de declarar explícitamente una transacción autónoma está claro que es mucho mejor, más limpio. No recordaba esta característica nueva, gracias por proponerlo Gallosuarez.


La franja horaria es GMT +2. Ahora son las 09:28:03.

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