Anuncios en tutorial de programación PLSQL

viernes, 16 de marzo de 2018

Gestión de errores y ROLLBACKS, lo que hay que saber

Es importante conocer el hecho de que cuando se produce un error PLSQL no gestionado dentro de una sección EXCEPTION, este hecho no supone que automáticamente se realice un ROLLBACK y que todos los cambios realizados en la base de datos Oracle desde el último COMMIT se deshagan.

Error PLSQL

De hecho, a menos que nuestro código incluya de forma explícita la sentencia ROLLBACK dentro de una sección EXCEPTION, o que el error no gestionado lo propaguemos hasta la aplicación desde la que estamos ejecutando nuestro código PL/SQL, no se producirá ningún ROLLBACK.

Para comprender cual es el funcionamiento lo mejor es acudir a un ejemplo.

Supongamos que escribimos un bloque de código PL/SQL en el que se ejecutan dos sentencias DML, por ejemplo, un DELETE y un UPDATE:
  • DELETE: Borramos los registros de todos los proveedores que incluyen en el nombre el texto “NO USAR”.
  • UPDATE: Actualizamos el número de IVA de todos los proveedores añadiendo al principio de dicho número el código del país del proveedor. Y esto lo hacemos sin tener en cuenta que el campo número de IVA está limitado a 12 caracteres, insuficientes para determinados proveedores no españoles.

El problema subyacente es que, cuando intentemos actualizar el campo número de IVA con un valor de más de 12 caracteres, la base de datos Oracle nos va a devolver el error:
ORA-12899: el valor es demasiado grande para la columna "COMPRAS"."PROVEEDORES"."NUMERO_IVA" (real: 15, máximo: 12)

El código PL/SQL podría ser el siguiente:
BEGIN

   DELETE FROM compras.proveedores
   WHERE UPPER(nombre_proveedor) LIKE '%NO USAR%';

   UPDATE compras.proveedores
   SET numero_iva = codigo_pais||numero_iva;

   EXCEPTION
      WHEN OTHERS
      THEN
        DECLARE
            l_num_prov_no_usar PLS_INTEGER;
         BEGIN
            SELECT COUNT (*)
              INTO l_num_prov_no_usar
              FROM compras.proveedores
             WHERE UPPER(nombre_proveedor) LIKE '%NO USAR%';
            DBMS_OUTPUT.put_line (l_num_prov_no_usar);
            RAISE;
         END;

END;

Ahora supongamos que lo ejecutamos desde la aplicación Oracle SQL Developer.

El resultado será que la sentencia DELETE se ejecutará correctamente, pero la base de datos Oracle generará el error ORA-12899 cuando esté intentando ejecutar el comando UPDATE. El código recogerá el error y mostrará el número de registros de la tabla COMPRAS.PROVEEDORES cuyo campo NOMBRE_PROVEEDOR contiene el texto “NO USAR”. Dicho número de registros será “0”, ya que el error se ha producido durante el UPDATE, cuando ya se ha ejecutado la sentencia DELETE y sin que se haya ejecutado un ROLLBACK.

Después de mostrar el número de registros, se vuelve a generar la misma excepción con la sentencia RAISE. Debido a que la sección EXCEPTION no está dentro de otro bloque, el código PL/SQL devuelve un error no gestionado a la aplicación Oracle SQL Developer. Puesto que el comportamiento por defecto de Oracle SQL Developer, y de todas las aplicaciones de base de datos que yo conozco, es ejecutar un ROLLBACK cuando recibe un error, finalmente la sentencia DELETE no tendrá efecto.

Por lo tanto, los proveedores con el texto “NO USAR” seguirán existiendo en la tabla COMPRAS.PROVEEDORES y la salida del código que hemos escrito nos podría llevar a engaño.

0 comentarios: