No todos los errores podemos atrapar con las excepciones. Eso sería lo ideal pero el estándar SQL supone que algunos errores serán evitados a nivel de lenguaje de programación, no a nivel de la Base de Datos.

Veamos un ejemplo:

Tenemos una tabla llamada NOMBRES, con esta estructura:

ERRORES1

Captura 1. Si haces clic en la imagen la verás más grande

y una tabla para registrar los ERRORES que tiene esta estructura:

ERRORES2

Captura 2. Si haces clic en la imagen la verás más grande

También un stored procedure para actualizar o insertar filas a la tabla NOMBRES, cuyo código fuente es el siguiente:

SET TERM ^ ;

CREATE PROCEDURE GRABAR_NOMBRES(
   IDENTI TYPE OF COLUMN NOMBRES.NOM_IDENTI,
   NOMBRE TYPE OF COLUMN NOMBRES.NOM_NOMBRE)
AS
BEGIN

   UPDATE OR INSERT INTO NOMBRES
                   (NOM_IDENTI, NOM_NOMBRE)
            VALUES (:Identi   , :Nombre ) ;

   WHEN ANY DO
      IN AUTONOMOUS TRANSACTION DO
         INSERT INTO ERRORES
                    (ERR_MODULO      , ERR_COMENT)
             VALUES ('GRABAR_NOMBRES', 'No se grabó el nombre');

END^

SET TERM ; ^

La idea sería, que si hay un error en el UPDATE OR INSERT se agregue una fila a la tabla ERRORES para tener registrado que ocurrió ese error. Sin embargo, si escribimos algo como:


EXECUTE PROCEDURE GRABAR_NOMBRES(0, 'JUAN567890123456789012345');

no se inserta una fila en la tabla ERRORES. Tampoco se insertará si en lugar de un stored procedure escribimos un trigger:

SET TERM ^ ;

CREATE TRIGGER NOMBRES_BIU FOR NOMBRES
   ACTIVE BEFORE INSERT OR UPDATE
   POSITION 1
AS
BEGIN

   IN AUTONOMOUS TRANSACTION DO
      INSERT INTO ERRORES
                 (ERR_MODULO   , ERR_COMENT)
          VALUES ('NOMBRES_BIU', 'Ocurrió un error');

END^

SET TERM ; ^

¿Por qué, qué pasó, por qué en ninguno de esos casos conseguimos que se inserte una fila en la tabla ERRORES?

La respuesta es que el Firebird (y todos los SGBD que cumplen con el estándar SQL) cuando encuentra que hay un error en los tipos de datos de un INSERT o de un UPDATE ya rechaza esa inserción o actualización, no continúa.

En nuestro ejemplo el dato que queríamos insertar en la columna NOM_NOMBRE tenía más de 20 caracteres y la columna NOM_NOMBRE está definida como VARCHAR(20). Lo mismo hubiera sucedido si por ejemplo en una columna numérica queremos guardar un dato alfabético: el Firebird lo rechaza sin contemplaciones.

Y eso implica que no podremos agregarle una fila a la tabla ERRORES que nos diga algo como: “la cantidad de caracteres que se quisieron grabar en la columna NOM_NOMBRE es mayor que 20”.

Por lo tanto, la única alternativa posible es que en nuestro programa, en nuestro lenguaje de programación, realicemos esa validación.

Conclusión:

Hay algunos errores que no se pueden atrapar con la construcción WHEN …. DO, y esos son los errores debidos a tipos de datos incorrectos. Por ejemplo, si en una columna definida como VARCHAR(20) queremos guardar más de 20 caracteres nuestro intento será rechazado pero no se ejecutarán las instrucciones del WHEN … DO que tengamos a continuación. Lo mismo ocurriría si en una columna de tipo numérico queremos insertar caracteres alfabéticos. O de tipo fecha. O de tipo hora, etc.

Artículo relacionado:

El índice del blog Firebird21